动态安排提醒邮件的最佳方式是什么?有比cron更好的选择吗?

6
问候,我正在开发一个Web应用程序。其中一部分将允许用户安排在特定时间发送“提醒”电子邮件给他们。有什么最好的方法来实现这一点?基本上,我想要的是“中断”模式,而不是“轮询”模式。
以下是我想出的一些可能的解决方案:
1. 每分钟触发一个cronjob。触发脚本会检查数据库是否有需要发送的电子邮件,如果有,则发送它们,否则就休眠。缺点是每分钟都会产生一些开销。并且,当用户数量变得非常大时,可能需要超过一分钟才能发送所有电子邮件,因此这可能不是可扩展的系统。
2. 与第1种相同,但只在每15分钟触发一次任务。这更加可管理,但仍然有一些开销,尤其是当没有需要发送的电子邮件时。虽然不错,但也不完美。
3. 在PHP中使用exec()执行一些代码,动态更改crontab或在底层Linux中安排“at”作业。这将为我提供所需的灵活性和“中断”类型模型,但将在允许PHP执行Linux代码时打开巨大的安全漏洞。因此,我将放弃这个选项。
那么,有比我想出的更好的方法吗?也许有一种不使用cron来安排电子邮件的方法?我非常想知道您对此有何看法 :)。

1
即使是 Postfix 开发人员也建议使用 cron 作业进行邮件调度。顺便说一下,小心谨慎地使用 exec 是没有问题的。与其它代码中注释努力不懈相比,由于 PHP 缓冲区溢出,利用更有可能发生。 - mario
类似这个问题:https://dev59.com/_W015IYBdhLWcg3w_Qw_ - Kizz
5个回答

3
您可以编写一个保持运行的PHP脚本。每个设置的间隔,查询数据库中需要在下一个间隔发送的电子邮件。将其拆分成一个数组,每分钟一个组。因此,如果选择15分钟,则将拥有一个具有15个条目的数组,每个条目都有需要在该时间发送的所有电子邮件。
然后,您可以使用forking来分割该过程,一个处理发送电子邮件,另一个睡眠直到下一分钟并再次分割。要进行扩展,您可以分叉多个进程,每个进程处理一定数量的电子邮件。
简而言之,一个进程管理队列并分叉其他进程来处理发送。当队列为空时,它会获取更多内容。您可以定期运行cron以确保该进程未死亡。

2

使用第一种变体。

发送所有电子邮件可能需要超过一分钟的时间

  1. 检查,如果file_exists('mailing.q')返回True,则终止执行。
  2. 创建文件mailing.q
  3. 发送电子邮件
  4. unlink('mailing.q')

不要考虑开销 - 在这种情况下不需要。


2
在选项#1和#2中使用cron没有什么特别的问题,我不知道您使用的是什么应用程序,但是给用户安排到具体分钟可能并不必要。即使如此,如果您的脚本将提醒的状态标记为“待定”或其他类似状态,在脚本的任何新实例中只发送那些不是“待定”或“已发送”的提醒,这可能也不会成为问题。
您可以使用Hudson或类似的应用程序来帮助进行脚本管理,并能够在出现故障时检查并发送通知。它甚至支持自己的基于Java的cron系统。
如果应用程序变得庞大,您肯定会想将此过程从Web服务器转移到单独的服务器上。此外,如果您还没有使用外部SMTP服务,则可能需要查看第三方邮件发送工具,并了解它们可能具有的集成工具,以提高交付率等。

+1 建议使用外部邮件服务。外部邮件服务可以保护您免受意外黑名单的影响,这种情况比您想象的更常见,我的电子邮件营销朋友说... - drkstr

1
不要混淆排队发送邮件和实际发送邮件。
您的邮件服务器可能需要十五分钟才能发送一封电子邮件。但是我的mail(1)只需要0.036s来排队发送邮件消息。
即使您最终每分钟需要发送超过1600封电子邮件(做得好!),您也可以稍微调整代码,以便在几分钟之前概率地开始发送提醒邮件,以应对“高峰”——例如,向前查看您的数据库五分钟,看看是否有>1000封邮件要发送,并以1/5、1/4、1/3、1/2的概率排队发送剩余的邮件。

0
有一个命令hostman,它允许你在特定的时间调用一个函数。这应该可以满足你的需求。

这是我的原始建议:

那么结合一下怎么样?

  1. 设置一个 cron job,每隔一段时间运行一次。
  2. 让它填充一个文件,其中包含一个时间戳 => 列表,反映了在 <current time> + <timespan> 之前是否有电子邮件。
  3. 设置第二个 cron job,每分钟运行一次,如果在电子邮件列表文件中找到了时间,则运行电子邮件发送脚本。

1
cron也允许您在特定时间执行函数,是吗? - Jeff

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