PHP、sendmail 和 Transports - 如何加快邮件发送速度
我刚刚编写了一组批量电子邮件发送类,用于处理大量电子邮件并根据传递的参数解析其内容。如果我对数据库中的 1000 个随机收件人和 1000 个随机发件人测试一封电子邮件,直到脚本到达 send() 部分(我现在对此进行了评论),我得到的性能约为 2 秒,峰值内存为 20 MB ,这太棒了。
但是,如果我取消注释发送部分,则发送需要 30 秒。这是不可接受的,我想以某种方式加快速度。从测试中可以明显看出,延迟是由 $mail->send() 调用引起的,就好像它在继续循环并发送下一封电子邮件之前等待它返回某些内容一样。
我想知道的是:如何加快 send() 调用速度?我该怎么做才能让它更快?我尝试使用两种发送方法:
- Zend SMTP 传输,直接连接到服务器并发送。每 1000 封电子邮件需要 30 秒。
- 通过 Zend_Mail 发送邮件。只需在准备好每封电子邮件后调用 Zend_Mail 的发送函数即可。这需要 60 秒。
请注意,排队绝对是一种选择,我已将其内置到我的课程中。只需要激活一个 cron,它就会像魅力一样发挥作用。但我想知道实际的发送以及如何加快发送速度。所以,实际的 send() 调用。
I just wrote a set of bulk-emailing classes for handling enormous amounts of emails and parsing their content according to passed params. If I test an email on 1000 random recipients and 1000 random senders from my database, up until the point the script hits the send() part (I commented it for now), I get performance of around 2 seconds, and 20 MB peak memory, which is great.
However, if I uncomment the send part, the sending takes 30 seconds. This is unacceptable, and I would like to speed it up somehow. It is obvious from testing that the delay is caused by none other than the $mail->send() call, as if it's waiting for it to return something before continuing the loop and sending the next email.
What I'm wondering is: how do I speed up the send() call? What can I do to make it faster? I tried using two sending methods:
- Zend SMTP transport, connecting to the server directly and just sending. This takes 30 seconds per 1000 emails.
- Sendmail via Zend_Mail. Simply calling Zend_Mail's send function after preparing each email. This takes 60 seconds.
Please note that queueing is definitely an option, and I have built it into my classes. All it takes is activating a cron and it works like a charm. But I'm wondering about the actual sending and how to speed that up. So, the actual send() call.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我将邮件保存在一个目录中并使用 shell 脚本(cron/daemon/...)发送它们:
I'd save the mails in a directory and send them using a shell script (cron/daemon/...):
您需要加快服务器上的 MTA 速度。我推荐 Postfix,并且您应该认真阅读每个设置,这样您就知道如何对其进行微调。对于商业解决方案,我听说 PowerMTA 是一个不错的选择,但我自己从未尝试过。
一台机器的性能有限,但是一旦正确配置,常规的专用服务器应该能够传送相当数量的邮件。最大的性能瓶颈通常是存储邮件队列的磁盘驱动器,因此请考虑使用 SAS(10k 甚至 15k RPM)或 SSD 驱动器。
You will need to speed up the MTA on the server. I recommend Postfix and that you really read up on each setting so you know how to fine-tune it. For a commercial solution I've heard PowerMTA is a good choice but I've never tried it myself.
There's only so much performance you can squeeze out of one machine, but a regular dedicated server should be able to deliver a rather impressive amount of mail once you've configured it correctly. The biggest performance bottleneck is usually the disk drives where the mail queue is stored, so consider using SAS (10k or even 15k RPM) or SSD drives.
您可以尝试深入研究 PHP pcntl-fork 函数。因此,您可以在解析下一封电子邮件时将发送留在另一个进程中。
B 计划
您可以序列化电子邮件对象并将其保存到数据库队列中,并让另一个脚本在后台发送它们。该脚本可以在无限循环(
while true
)中运行,并在每次迭代时进行一些睡眠
。您甚至可以运行此脚本的多个实例,但请确保两个脚本不会同时开始发送同一封电子邮件。要确保脚本仍在运行,您可以在 Unix 计算机上使用 monit 。如果旧实例由于某种原因失败,它可以启动脚本。
You could try to dig into PHP pcntl-fork function. Thus you could leave the sending in another process while parsing the next email.
PLAN B
You can serialize and save the email object into a database queue and let another script to send them in the background. This script could run in infinite loop (
while true
) with somesleep
on every iteration. You can even run multiple instances of this script, but be sure that two scripts won't start sending the same email simultaneously.To be sure that the script is still running you can use monit on Unix machines. It is able to start the script if the old instance has failed for some reason.