提高发送java邮件的速度

提高发送java邮件的速度,java,sql,multithreading,email,smtp,Java,Sql,Multithreading,Email,Smtp,我用Java编写了一个代码,使用Java mail通过smtp服务器发送邮件。发件人和收件人的电子邮件地址以及邮件的主题和正文保存在数据库(sql)中。然而,以这种方式发送邮件相当慢。我必须发送大量邮件(大约300封/秒)。如何使用多线程提高发送邮件的速度 import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.Properties; import ja

我用Java编写了一个代码,使用Java mail通过smtp服务器发送邮件。发件人和收件人的电子邮件地址以及邮件的主题和正文保存在数据库(sql)中。然而,以这种方式发送邮件相当慢。我必须发送大量邮件(大约300封/秒)。如何使用多线程提高发送邮件的速度

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import oracle.jdbc.OraclePreparedStatement;

public class mainclass {

Properties emailProperties;
Session mailSession;
MimeMessage emailMessage;



public static void main(String args[]) throws AddressException,
        MessagingException {
            OraclePreparedStatement pst;
            Connection con;
            String userna;
            con = connectDB.connect();
            try {
                    Statement st = con.createStatement();
                    String sm = "SELECT * FROM EmailQueue WHERE sent = 'no'";
                    ResultSet res = st.executeQuery(sm);
                    while (res.next()) {
                        System.out.println(res.getString("from_email_address") + " " + res.getString("to_email_address"));
                        String id = res.getString("id");
                        String toEmails = res.getString("to_email_address");
                        String emailSubject = res.getString("subject");
                        String emailBody = res.getString("body");
                        String emailHost = "smtp.gmail.com";
                        String fromUser = res.getString("from_email_address");
                        String fromUserEmailPassword = res.getString("password");
                        mainclass javaEmail = new mainclass();
                        javaEmail.setMailServerProperties();
                        javaEmail.createEmailMessage(toEmails, emailSubject, emailBody);
                        javaEmail.sendEmail(emailHost, fromUser, fromUserEmailPassword);
                        Statement sn = con.createStatement();
                        String up = "Update EmailQueue set sent='yes' where id='"+id+"'";
                        sn.executeQuery(up);
                    }

        } catch(Exception e) {
            System.out.println("problem");
        }


}

public void setMailServerProperties() {

    String emailPort = "587";//gmail's smtp port

    emailProperties = System.getProperties();
    emailProperties.put("mail.smtp.port", emailPort);
    emailProperties.put("mail.smtp.auth", "true");
    emailProperties.put("mail.smtp.starttls.enable", "true");

}

public void createEmailMessage(String toEmails, String emailSubject, String emailBody) throws AddressException,
        MessagingException {

    mailSession = Session.getDefaultInstance(emailProperties, null);
    emailMessage = new MimeMessage(mailSession);

        emailMessage.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmails));


    emailMessage.setSubject(emailSubject);
    emailMessage.setContent(emailBody, "text/html");//for a html email
    //emailMessage.setText(emailBody);// for a text email

}

public void sendEmail(String emailHost, String fromUser, String fromUserEmailPassword) throws AddressException, MessagingException {


    Transport transport = mailSession.getTransport("smtp");

    transport.connect(emailHost, fromUser, fromUserEmailPassword);
    transport.sendMessage(emailMessage, emailMessage.getAllRecipients());
    transport.close();
    System.out.println("Email sent successfully.");
}

}

多线程发送邮件的过程只会导致邮件服务器出现数千个请求


当您发送电子邮件(例如JavaMail)时,您只是向邮件服务器提交一封新邮件。邮件服务器将实际向收件人发送邮件。在Java方面,您无法提高发送速度。

快速发送大量电子邮件的关键是多线程——无论是在Java代码中还是在电子邮件服务器的配置中

当您通过JavaMail发送电子邮件时,您实际上只是将邮件提交到SMTP电子邮件服务器。然后,SMTP服务器查找接收域的MX地址(电子邮件地址中“@”之后的部分)以获取接收SMTP服务器的IP地址。然后,它开始与接收SMTP服务器进行对话,最终导致邮件被传输。由于许多原因,这一过程可能进展非常缓慢。 -查找接收服务器的IP地址的过程可能需要时间 -与接收SMTP服务器的对话可能非常缓慢,具体取决于其负载和策略。有些对话实际上需要几分钟

因此,要加快电子邮件应用程序的吞吐量,您应该: 1) 确保SMTP服务器本地有一个缓存名称服务器。这将使其识别接收SMTP的IP的过程更快。基本上,缓存名称服务器会在本地记住过去的查找请求,因此对同一域的后续请求要快得多(可能快100倍)。换句话说,一旦你查找了“gmail.com”的接收IP地址,你就不需要再查找它,直到它的TTL过期。在Red Hat linux上,可以通过“yum install caching nameserver”将bind配置为缓存名称服务器

2) 将SMTP服务器配置为具有多个线程。由于大多数情况下,您的SMTP服务器将等待其他服务器进行“对话”,它可以有效地同时进行数百次对话。我使用Postfix是因为它快速可靠。默认情况下,Postfix配置为同时有100个SMTP进程。我把这个数字提高到300或更多。在Postfix中,您可以使用默认的\u进程\u限制设置配置此进程限制

3) 调整SMTP服务器,以考虑到某些接收服务器速度非常慢或完全没有响应。例如,默认情况下,Postfix被配置为等待300秒(五分钟!),以便接收服务器响应其初始“HELO”。通过设置smtp\u helo\u timeout=100s的配置选项,我将此时间缩短到100秒。由于接收服务器速度较慢而未成功发送的邮件将由SMTP服务器排队,以便稍后重试


4) 在使用JavaMail时使用多线程。我在Java代码中创建多线程的速度提高了很多。这样,就可以同时与我的SMTP服务器进行许多对话

这取决于瓶颈所在的位置,但现有的主线程可以继续从数据库中读取行,但可以将作业发送到线程池,以创建执行
sendMessage
mainclass
实例。当主线程继续从数据库中读取行时,我创建了一个线程池来发送邮件。@user3804428我能看看你是如何提高线程速度的吗