1

我们有一个 Web 应用程序,它使用 IMAP 在用户定义的时间有条件地将消息插入用户的邮箱。

这些“作业”中的每一个都存储在 MySQL 数据库中,并带有一个时间戳,表明作业应该运行的时间(可能是未来几个月)。用户可以随时取消作业。

问题是建立 IMAP 连接是一个缓慢的过程,在我们插入消息之前,我们经常必须有条件地检查收件箱中是否有某人的回复(或类似的),这给每个作业增加了相当大的处理开销。

我们目前有一个系统,其中每分钟左右运行一次 cron 脚本,以便从数据库中获取所有需要在接下来的 X 分钟内交付的作业。然后,它将它们分成几批 Z 作业,并为每批执行一个异步 POST 请求,将这些 Z 作业的所有数据返回到同一台服务器(以实现“假”多线程)。然后,服务器处理通过 HTTP 传入的每批 Z 作业。

我们为多线程使用异步 HTTP POST 而不是 pnctl_fork 之类的原因是,我们可以添加其他服务器并让它们将数据 POST 到这些服务器,并让它们运行作业而不是当前服务器。

所以我的问题是 - 有没有更好的方法来做到这一点?

我很欣赏可以使用像beanstalkd这样的工作队列,但它们是否符合必须在特定时间运行作业的模型?

另外,因为无论如何我们都需要将作业保留在数据库中(因为我们需要为用户提供用于管理作业的 UI),所以在某处添加工作队列实际上会增加而不是减少开销吗?

我确信有更好的方法来实现我们的需要 - 任何建议都将不胜感激!

我们正在使用 PHP 来解决所有这些问题,因此我们正在寻找基于 PHP/兼容的解决方案。

4

1 回答 1

0

Beanstalkd 将是一种合理的方式来做到这一点。它具有 的概念put-with-delay,因此您可以定期从您的主存储队列中填充一条消息,该消息将能够被保留并在X几秒钟内运行(您希望它-现在运行的时间)。

然后工作人员将正常运行,连接到 beanstalkd 守护程序并等待保留新作业。如果没有 HTTP 连接的开销,它也会更有效。例如,我曾经将消息发布到 Amazon SQS(通过 http)。这最多只能做到 20 QPS,但 Beanstalkd 几乎不费吹灰之力就接受了每秒超过 1000 个 QPS。

编辑添加: 您无法在不知道其 ID 的情况下删除作业,尽管您可以将其存储在外部。OTOH,用户是否必须能够在最后一分钟之前随时删除作业?您不必提前几周或几个月将作业放入队列中,因此您仍然只有一个 DB-reader 每隔 1 到 5 分钟运行一次,以便将接下来的几个作业放入队列中,并且仍然有尽可能多的工人,他们可以带来效率。

最终,这取决于您正在执行的数据库读取/写入次数,以及数据库服务器如何处理它们。

如果你正在做的事情现在不是问题,并且不会因为额外的负载而变得如此,那么继续。

于 2012-01-23T18:44:12.470 回答