在 Elastic Beanstalk 中运行 cron 作业
Posted
技术标签:
【中文标题】在 Elastic Beanstalk 中运行 cron 作业【英文标题】:Running a cron job in Elastic Beanstalk 【发布时间】:2016-11-26 03:45:32 【问题描述】:所以我在 Django Elastic Beanstalk 应用程序中有一个功能如下:
下载文件 解析文件,使用文件中的数据运行一些 API 调用 用新数据更新 EB 实例的数据库在我刚刚设置本地 cron 作业的测试实例中。我刚刚在我的 Django 应用程序的特定 URL 上调用了wget
,它将运行该命令。
我的问题是如何在多实例 Elastic Beanstalk 应用程序中处理这个问题。只有我的 EB 应用程序的一个实例应该运行此命令。我想避免数据库上的竞争条件和从多个实例对外部 API 的冗余调用。即只有一个实例应该写入数据库。
但是,谷歌搜索显示设置 cron 作业很尴尬,特别是如果您像我一样是 EB 新手。听起来最有前途的方法似乎是cron.yaml
方法,但据我所知,似乎没有在网络上任何地方设置 cron 工作环境的示例。
我的理解是:
您在 EB 项目的根目录中包含一个 cron.yaml 文件。 部署项目 cron 作业是在工作环境中自动设置的 (?)。 您定义的命令在指定时间运行。我的问题是如何确保只有一个实例会运行此命令?我对cron.yaml
的工作原理是否有正确的想法,或者我缺少什么
【问题讨论】:
【参考方案1】:只有一个实例会运行该命令,因为 cron 作业实际上并未在 cron 守护程序本身中运行。
很少有概念可以帮助您快速了解亚马逊的 Elastic Beanstalk 思维方式。
弹性 beanstalk 环境必须选择一个领导者实例,该领导者实例必须永远只有一个(并且它必须是一个健康的实例等)。 工作环境通过 SQS(简单队列服务)队列分配工作。 一旦从队列中读取了一条消息,它就会被视为“正在进行中”,直到工作人员返回 200 或请求超时/失败。在第一种情况下,消息被删除,在后一种情况下,它重新进入队列。 (重新驱动策略可以确定消息在发送到死信队列之前失败的次数) 无法再次阅读飞行中的消息(除非返回)。队列中的消息一次只能被工作环境中的一个实例拾取一次。
现在cron.yaml
文件实际上只是告诉领导者在调度中指定的时间在队列中创建具有特殊属性的消息。然后,当它找到此消息时,它仅作为对指定 URL 的 POST 请求分派到一个实例。
当我在工作环境中使用 Django 时,我创建了一个 cron
应用程序,其中包含映射到我想要的操作的视图。例如,如果我想定期轮询 Facebook 端点,我可能有一个路径 /cron/facebook/poll/
,它在 views.py 中调用 poll_facebook()
函数
这样,如果我有如下的 cron.yaml,它将每小时轮询一次 Facebook:
version: 1
cron:
- name: "pollfacebook"
url: "/cron/facebook/poll/"
schedule: "0 * * * *"
【讨论】:
经过多次试验和错误最终发现了这一点,很高兴为其他有此问题的人提供最终答案。以上是关于在 Elastic Beanstalk 中运行 cron 作业的主要内容,如果未能解决你的问题,请参考以下文章
在 AWS Elastic Beanstalk 上使用 Docker 预编译资产
在 Elastic Beanstalk 中运行 cron 作业
为啥 Docker 构建命令在 Elastic Beanstalk 中运行如此缓慢?
Celery 可以在 Elastic Beanstalk 上运行吗?