0

我最近将Symfony项目从手动缩放EC2环境移至Elastic Beanstalk,并且我偶然发现了一个问题。Amazon ElasticBeanstalk中的单实例cronjob

我有一个Cron作业,抓住了一堆已满的订阅,并尝试创建订单并对它们进行收费,因此这项工作只能在单个服务器上运行,这一点非常重要,因为它在批处理中抓取它们,如果有重复的Cron正在运行,它将导致相同订阅的多项费用。

在手动扩展环境中,我只有一台主服务器,它有一个crontab并运行了子服务器,但在这里看起来并不可行。

有关如何在没有主服务器的自动扩展环境中进行设置的任何建议?

我已经看过JMSJobQueueBundle,但它似乎也依赖于只运行crontab的单个实例的主管,这将在自动扩展环境中重复。

我最好是有一个外部服务器每隔X分钟对我的API进行ping操作,并在单个实例上启动它的ping工作?这似乎引发了另一个失败点。

回答

2

就像一个警告,你试图解决的问题不是一个微不足道的问题。

有几个选项:

  1. 如果你连接到MySQL数据库,掌握在事务开始时的锁(https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock),并在年底解除锁定。这会阻止多个cronjob同时运行代码。只有在SQL中处理所有内容时才有效。

  2. 如上所述,您可以使用AWS Lambda + CloudWatch Events每x分钟触发一次Lambda函数,并且Lambda可以通过http(s)触发脚本。但是拉姆达并不能保证这样做只是一次,所以这是不安全的。

  3. 使用一种服务,您可以获取分布式锁(例如etcd,consul,redis,...)并以与1相似的方式实现,而不仅仅是在您的MySQL数据库中。尽管如此,你仍然可以或者真的只有一次。

  4. 把cronjob放在一个单独的ec2实例上,你知道它只存在一次(如果这个ec2实例发生故障,什么都不会运行,但据我了解你的要求,这不是问题,因为脚本可以在以后运行15分钟,仍与所有工作赶上。

在分布式系统中的更“现代”的方法是使你的行动幂等。

+0

我将试图建立一个工人。 –