【问题标题】:Single instance cronjob in Amazon ElasticBeanstalkAmazon ElasticBeanstalk 中的单实例 cronjob
【发布时间】:2017-07-13 20:31:54
【问题描述】:

我最近将我的 Symfony 项目从手动扩展的 EC2 环境迁移到 Elastic Beanstalk,但我偶然发现了一个问题。

我有一个 Cron 作业,它抓取一堆过期的订阅,并尝试创建订单并收取费用,这项作业仅在单个服务器上运行非常重要,因为它会批量抓取它们,如果有一个重复的 Cron 正在运行,这将导致对同一个订阅进行多次收费。

在手动扩展环境中,我只有一个主服务器,它有一个 crontab 并运行 subs,但在这里似乎不可行。

关于如何在没有主服务器的自动缩放环境中进行设置有什么建议吗?

我研究了 JMSJobQueueBundle,但它似乎也依赖于只运行单个 crontab 实例的主管,这在自动缩放环境中会重复。

最好让外部服务器每 X 分钟 ping 我的 API 并在它 ping 的单个实例上启动作业?这似乎引入了另一个故障点。

【问题讨论】:

    标签: symfony amazon-web-services amazon-elastic-beanstalk autoscaling


    【解决方案1】:

    作为一个警告,您要解决的问题并非微不足道。

    几个选项:

    1. 如果您连接到 MySQL 数据库,请在事务开始时获取锁 (https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_get-lock),并在结束时释放锁。这将防止多个 cronjobs 同时运行代码。仅当一切都在 SQL 中处理时才有效。

    2. 正如您所提到的,您可以使用 AWS Lambda + CloudWatch Events 每 x 分钟触发一次 Lambda 函数,然后 Lambda 可以通过 http(s) 触发您的脚本。但是 lambda 不保证它只执行一次,所以这是不安全的。

    3. 使用可以获取分布式锁的服务(例如 etcd、consul、redis 等)并以与 1 类似的方式实现,只是不在 MySQL 数据库中。你仍然不能用它来做一次。

    4. 将 cronjob 放在一个单独的 ec2 实例上,您知道它只存在一次(如果此 ec2 实例出现故障,则不会运行任何东西,但据我了解您的要求,这不是问题,因为脚本可以在 15 分钟后运行,并且仍能赶上所有工作。

    分布式系统中更“现代”的方法是让您的操作具有幂等性。

    【讨论】:

      猜你喜欢
      • 2013-12-20
      • 1970-01-01
      • 2016-04-16
      • 2020-09-24
      • 2018-11-05
      • 2013-03-04
      • 1970-01-01
      • 2013-12-20
      • 2014-04-24
      相关资源
      最近更新 更多