简体   繁体   English

改善通过Spring邮件发送批量电子邮件的性能

[英]Improve performance on sending bulk emails through spring-mail

I have a spring-stand alone application which uses simple spring email code as below , the to and the message is constructed using the values iterated from map. 我有一个独立于Spring的应用程序,它使用以下简单的Spring电子邮件代码, tomessage是使用从map迭代的值构造的。

I have already had some suggestions for the question here , but i am in need of some specific advise for this. 这里 ,我已经对这个问题提出了一些建议,但是我需要一些具体的建议。 below is my code 下面是我的代码

for (Map.Entry<String, List<values>> entry : testMap
                .entrySet()) {
            String key = entry.getKey();
            StringBuilder htmlBuilder = new StringBuilder();            
            List<Model> valueList = entry.getValue();
            for (Model value : valueList) {
                htmlBuilder.append('List Values in the message');
            }
            mail.sendMail( msgFrom,body); // call my sendMail function in another class
        } 

Code for sending mail : 发送邮件的代码:

        MimeMessage email = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(email, true);
        helper.setFrom(new InternetAddress(from));
        helper.setTo(new InternetAddress(to));
        helper.setText(msg, true);
        helper.addInline("identifier1234", res);
        mailSender.send(email);

It takes 3 to 4 seconds to send mail . 发送邮件需要3到4秒钟。 I have large user list of around 400,000 each day to be sent 我每天有大约40万个大型用户要发送

Am i doing anything wrong or anyother approach to fasten this process. 我在做任何错误的事情还是其他方法来加快此过程。 I am in need of experts advise 我需要专家的建议

Thanks for your time and help :) 感谢您的时间和帮助:)

IMHO, the process of sending mail itself can be improved, because currently, you open an new connection to mail server per message. 恕我直言,可以改进发送邮件本身的过程,因为当前,您为每条消息打开到邮件服务器的新连接。 You could improve it by using batched sending. 您可以通过使用批量发送来改进它。

Spring MailSender interface natively supports sending of an array of messages instead of a single one, so you do not have do explicitely deal with JavaMail Session. Spring MailSender接口本机支持发送一系列消息,而不是单个消息,因此您不必显式处理JavaMail Session。 You could simply modifiy the class actually sending the mail that way 您可以简单地修改实际以这种方式发送邮件的类

int batchSize = 16; // for example, adjust it to you needs
MimeMessage[] messages = new MimeMessage[batchSize];
int messageIndex = 0;

public void sendMail(String msgFrom, String body) {
    // prepare MimeMessage
    messages[messageIndex++] = email;
    if (messagesIndex == batchSize) {
        mailSender.send(messages);
        messageIndex = 0;
    }

public void sendLastMails() {
    if (messageIndex > 0) {
        MimeMessage[] lastMessages = new MimeMessage[messageIndex];
        for (int i =0; i<messageIndex; i++) {
            lastMessages[i] = messages[i];
    }
    mailSender.send(lastMessages);
}

Edit: 编辑:

The sendLastMails method may be called in several places. sendLastMails方法可以在几个地方调用。 First, it must be called in the destroy method of a singleton bean to make sure no messages are forgotten when application closes. 首先, 必须在单例bean的destroy方法中调用它,以确保在应用程序关闭时不会忘记任何消息。 If the class sending mail is a singleton bean, it is enough to declare that the destroy method for the bean is sendLastMail , or calls it. 如果发送邮件的类是单例bean,则足以声明该bean的destroy方法 sendLastMail或对其进行调用。

Then depending on you own business rules, it may be called after a batch of mails have been sent. 然后,根据您自己的业务规则,可能会在发送一批邮件后调用它。 Typical usage : in you example, you have testMap . 典型用法:在您的示例中,您具有testMap You should rewrite it that way : 您应该这样重写它:

    for (Map.Entry<String, List<values>> entry : testMap
            .entrySet()) {
        ...
        mail.sendMail( msgFrom,body); // call my sendMail function in another class
    }
    mail.sendLastMails();

Now it is up to you to see if this improvement is enough or if you should outsource. 现在由您决定是否可以进行此改进,还是应该外包。

Basically the answer is to not do this yourself. 基本上,答案是自己不要这样做。

Here is a very detailed reason why not: How to send 100,000 emails weekly? 为什么不这样做有一个非常详细的原因: 如何每周发送100,000封电子邮件?

您可以将sendMail封装到单独的Runnable类中,然后将任务放入ExecutorService中(或使用sendMail方法上方的@Async,但这很难进行配置-只是我的看法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM