使用PHP SwiftMailer和SMTP发送通讯邮件

5
我每天向约20K的收件人发送新闻简报。在更换服务器后,即使使用相同的PHP脚本,我需要花费大约六倍的时间来完成这项任务 - 我尝试了许多不同的设置,但没有成功(请参见此帖子)。邮件服务器似乎已经正确配置(关于垃圾邮件、中转和病毒),服务器运行Plesk 11.5.30。
通过进行许多实验,更改PHP脚本和Postfix设置,我能够使用以下方法实现最佳性能:
1. 使用SwiftMailer从PHP发送电子邮件。 2. 使用SMTP(本地帐户)作为传输。 3. 将收件人列表分成四个部分,并为每个部分启动单独的PHP-CLI进程。
当我只启动一个进程时,PHP每秒发送约5封电子邮件(与使用mail()函数发送电子邮件时相同)。Postfix在发送过程中没有任何问题,因此几乎没有队列。
当我启动四个进程时,PHP每秒发送约10封电子邮件,但是Postfix无法再“即时”发送它们(它只能每秒发送约5封电子邮件),因此队列变得越来越大。当PHP进程结束时,我的队列中有大约4500封电子邮件。有趣的是:当没有活动的PHP进程发送电子邮件时,Postfix会“加速”发送约20封电子邮件/秒。如果Postfix能够在PHP传递新电子邮件的同时以这种速度发送电子邮件,那么就不会有队列问题,这将解决我的问题。
我希望您能提供任何可以改善脚本和服务器发送新闻简报性能的想法。
以下是Postfix配置:
root@hostname:~# postconf -n 
alias_database = hash:/etc/aliases 
alias_maps = hash:/etc/aliases, hash:/var/spool/postfix/plesk/aliases 
append_dot_mydomain = no 
biff = no 
config_directory = /etc/postfix 
disable_vrfy_command = yes 
inet_interfaces = all 
inet_protocols = ipv4 
mailbox_size_limit = 0 
mailman_destination_recipient_limit = 1 
message_size_limit = 51200000 
mydestination = (none), localhost, localhost.localdomain, localhost 
mydomain = domain.com 
myhostname = myhostname.com 
mynetworks = 127.0.0.0/8 [::1]/128 my.ip.add.ress 
plesk_virtual_destination_recipient_limit = 1 
readme_directory = no 
recipient_delimiter = + 
relayhost = 
sender_dependent_default_transport_maps = hash:/var/spool/postfix/plesk/sdd_transport_maps 
smtp_connect_timeout = 10s 
smtp_helo_timeout = 100s 
smtp_send_xforward_command = yes 
smtp_tls_security_level = may 
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache 
smtp_use_tls = no 
smtpd_authorized_xforward_hosts = 127.0.0.0/8 [::1]/128 
smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU) 
smtpd_client_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_rbl_client zen.spamhaus.org 
smtpd_proxy_timeout = 3600s 
smtpd_recipient_restrictions = permit_mynetworks, check_client_access pcre:/var/spool/postfix/plesk/no_relay.re, permit_sasl_authenticated, reject_unauth_destination 
smtpd_sasl_auth_enable = yes 
smtpd_sender_restrictions = check_sender_access hash:/var/spool/postfix/plesk/blacklists, permit_sasl_authenticated, check_client_access pcre:/var/spool/postfix/plesk/non_auth.re 
smtpd_timeout = 3600s 
smtpd_tls_cert_file = /etc/postfix/postfix_default.pem 
smtpd_tls_key_file = $smtpd_tls_cert_file 
smtpd_tls_security_level = may 
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache 
smtpd_use_tls = yes 
transport_maps = , hash:/var/spool/postfix/plesk/transport 
virtual_alias_maps = $virtual_maps, hash:/var/spool/postfix/plesk/virtual 
virtual_gid_maps = static:31 
virtual_mailbox_base = /var/qmail/mailnames 
virtual_mailbox_domains = $virtual_mailbox_maps, hash:/var/spool/postfix/plesk/virtual_domains 
virtual_mailbox_limit = 0 
virtual_mailbox_maps = , hash:/var/spool/postfix/plesk/vmailbox 
virtual_transport = plesk_virtual 
virtual_uid_maps = static:110

我们使用一台专用服务器,实际上没有太多事情要做。 CPU 和内存不是问题 - 我们有足够的资源(我今天在发送通讯时再次检查了这一点)。 运行 iostat -m -x -d 5,我看到磁盘使用率非常高(%util 高达100% - 当 PHP 和 Postfix 完成后约为10% - 这可能与我们的性能问题有关吗?)我不明白的是,为什么新服务器上的 PHP 能够在一个进程中最多发送 5-7 封邮件/秒(如果只运行一个进程),而我们的旧服务器能够每秒发送 20 封或更多。 - Okizb
我不是服务器问题的专家,但任何事情的100%都值得进一步调查。它是否指出PHP和Postfix中哪个负责该使用级别? - halfer
邮件日志中没有关于“不合格的主机名”或“名称解析失败”的记录吗?当听起来好像一切都发生了变化时,“什么改变了”很难诊断。 - ficuscr
如果磁盘使用率达到100%,则smtpd和qmgr都会使磁盘超载。设置in_flow_delay尝试减缓传入电子邮件的速度。http://www.postfix.org/postconf.5.html#in_flow_delay。服务器之间差异的原因可能是黑名单检查(发件人限制)和DNS验证-请检查您是否有本地DNS缓存而不是外部DNS,如果可以,请使用本地黑名单或关闭本地发送的电子邮件的黑名单(在发件人限制中添加“permit_mynetworks”)。 - Robbie
或者您可以花费不到150美元/月的费用,将发送任务外包给电子邮件服务提供商,例如Mandrill,并将时间花在关注优质内容上,而不是CPU、正常运行时间和可交付性。 - Mike Causer
显示剩余2条评论
3个回答

2

由于你提到你的PHP进程每秒发送约5至20封电子邮件,我认为你已经详细测量了你的PHP代码,如果这个延迟是在PHP代码中,那么你应该已经发现了。

根据评论,我也认为你的系统相当庞大,所以你有足够的内存和磁盘空间。

在我的经验中,可能会导致这种延迟的一个常见问题是DNS解析,我指的是DNS的错误配置,这会导致全局延迟。但这个假设还需要证明。

另一方面,我还记得postfix有一个限制配置,以避免服务器滥用。 http://www.postfix.org/TUNING_README.html

最后,如果你在postfix配置中找不到任何问题,我建议你尝试使用strace工具调试postfix进程的执行过程。

这是一个非常有用的工具,当我需要调试非常规问题时经常使用它。

简单来说:strace列出了进程执行的所有系统调用。strace有很多可用选项,但我通常只使用以下几个:

strace -fp <pid of main process>

调试期间,您将看到由postfix主进程及其所有子进程执行的所有系统调用。如果添加 -c 选项,则会看到每个系统调用所花费的时间。


0

0

感谢您的所有答案和努力。幸运的是我能够找到问题的主要原因——将队列保存在硬盘上。我们将其更改为RAM,现在能够每秒发送约30封电子邮件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接