负载均衡的Web服务器上的Cron任务

15

我正在寻找更好的解决方案来处理负载均衡环境下的cron任务。

当前情况

  • PHP应用程序运行在负载均衡器后面的3台CentOS服务器上。
  • 需要定期运行的任务,但每次只能在一台机器上运行。
  • 设置了传统的cron以在第一台服务器上运行这些任务。
  • 如果第一个服务器因任何原因出现故障,则会出现问题。

希望达到的目标

  • 寻找更加健壮和去中心化的解决方案。
  • 负载均衡任务,使多个任务仅在随机/不同的服务器上运行一次,以分担负载。
  • 避免第一台服务器宕机时任务无法运行的情况。
  • 能够使用Web界面管理任务和查看聚合报告。
  • 通知如果出现任何问题。

解决方案不必实现在PHP中,但是如果可以这样做,那将使我们能够轻松地进行微调。

我已经找到了两个看起来很有前途的项目。 GNUBatchJob Scheduler。我很可能会进一步测试两者,但我想知道是否有更好的解决方案可以解决上述问题。

谢谢。


可以通过在最可靠的服务器(或完全不同的其他服务器)上设置cron作业,通过SSH随机在其中一台服务器上执行实际作业来解决逐个执行的问题。由于只有一台机器负责调度,因此您无需担心所有服务器之间的同步/锁定。 - Marc B
4个回答

7
你可以使用这个基于redis的小型库来创建一个临时计时锁: https://github.com/AlexDisler/MutexLock 服务器应该是相同的,并且具有相同的cron配置。第一个创建锁的服务器也将执行任务。其他服务器将看到锁并退出而不执行任何操作。
例如,在执行定时任务的php文件中:
MutexLock\Lock::init([
  'host'   => $redisHost,
  'port'   => $redisPort
]);

// check if a lock was already created,
// if it was, it means that another server is already executing this task
if (!MutexLock\Lock::set($lockKeyName, $lockTimeInSeconds)) {
  return;
}

// if no lock was created, execute the scheduled task
scheduledTaskThatRunsOnlyOnce();

为了以去中心化的方式运行任务并分散负载,请查看:https://github.com/chrisboulton/php-resque。这是 resque 的 php 版本,它以完全相同的格式存储数据,因此您可以使用 https://github.com/resque/resque-web 或者http://resqueboard.kamisama.me/来监视工作者并查看报告。


4
假设您有一个可用的数据库,不托管在这三个服务器之一上;编写一个“包装器”脚本,放入cron中,并将要运行的程序作为其参数。它所做的第一件事是连接到远程数据库,并检查最后插入表(为此包装器创建)的条目时间。如果最后插入时间晚于应该运行的时间,则在表中插入一个新记录,记录当前时间,并执行包装器的参数(您的cron作业)。
在每个服务器上都启动包装器,每个服务器设置为比其他服务器晚X分钟(服务器A在整点运行,服务器B在5分钟运行,C在10分钟运行,依此类推)。
第一个服务器将始终首先执行cron,因此其他两个服务器永远不会执行。如果第一个服务器崩溃,第二个服务器将看到它没有运行,并将运行它。
如果您还在表中记录了执行作业的服务器,您将拥有脚本执行的时间/位置日志。

谢谢Corey。我们已经找到了一些类似的解决方案。然而,这并不完全符合我们的标准,与纯cron相比,唯一的好处是如果第一个服务器崩溃,则可以回退到第二个或第三个服务器。问题不在于如何编写它,而在于是否已经有一个经过测试成熟的解决方案。 - poisson
我很好奇你现在在用什么? - Corey Henderson
我们只使用我在“当前拥有”部分中描述的内容。也就是说,cron直接在第一个框上触发所需的任务。 - poisson

0

这不是使用消息/任务队列的理想情况吗?


0

1
你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
“链接回答”被认为是非常低质量的,可能会被删除,请将链接资源中的重要部分放入答案正文中。 - helvete

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