通过spring-mail提高发送批量电子邮件的性能

时间:2014-10-07 07:54:57

标签: java spring performance email bulk

我有一个独立于spring-stand的应用程序,它使用如下的简单弹簧电子邮件代码,tomessage使用从map迭代的值构建。

我已经就问题here提出了一些建议,但我需要为此提出一些具体的建议。下面是我的代码

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
        } 

发送邮件的代码:

        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);

发送邮件需要3到4秒。我每天都有大约400,000个大型用户列表要发送

我做错了什么或任何其他方法来加快这个过程。我需要专家建议

感谢您的时间和帮助:)

3 个答案:

答案 0 :(得分:2)

基本上答案是不要自己这样做。

以下是一个非常详细的原因:How to send 100,000 emails weekly?

答案 1 :(得分:2)

恕我直言,发送邮件本身的过程可以得到改进,因为目前,你为每封邮件打开一个新的邮件服务器连接。您可以使用批量发送来改进它。

Spring MailSender接口本身支持发送一组消息而不是一个消息,因此您没有明确地处理JavaMail会话。你可以简单地修改实际发送邮件的类

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);
}

编辑:

可以在多个地方调用sendLastMails方法。首先,在单例bean的destroy方法中调用必须,以确保在应用程序关闭时不会忘记任何消息。如果发送邮件的类是单例bean,则足以声明bean 的destroy方法是 sendLastMail,或者调用它。

然后,根据您自己的业务规则,可能会在发送邮件后调用它。典型用法:在您的示例中,您有testMap。你应该这样重写:

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

现在由您来决定这种改进是否足够,或者您是否应该外包。

答案 2 :(得分:1)

您可以将sendMail包含在单独的Runnable类中,并将任务放入ExecutorService(或使用@Async以上的sendMail方法,但这很难配置 - 只是我的意见)。