我有一个运行 cakephp API 的 EC2 实例 (micro)。此实例在部署到生产之前提供质量验证。
在这个例子中,我们有 5 个 cronjob,每分钟运行一次。这些 cronjob 98% 的时间运行一个 Mysql 查询并终止,因为没有事情可做。所以基本上,98% 的时间,每分钟都会执行 5 个 mysql 查询。
这些 cronjobs 是使用 CloduWatch 事件 > 规则配置的,其中包含设置为文档的 5 个 cronjobs。以下是我们的一个文档的示例:
{ “schemaVersion”:“1.2”, “description”:“CronjobNumberOne”, “参数”:{
}, “runtimeConfig”: { “aws:runShellScript”: { “properties”: [ { “id”: “0.aws:runShellScript”, “runCommand”: [“ . /opt/elasticbeanstalk/support/envvars && /var/app/current/bin/cake cronjob_number_one > /var/log/cronjobs_php 2>&1”] } ] } } }
每次 cronjob 规则激活时,我们的 Ec2 实例的 CPU 使用率就会增加,并持续上升直到 Ec2 实例死机。以下图表显示了发生的情况:
我已经安装了 SAR 来检查一分钟内的 CPU 使用率,以下是发生的情况:
一旦我关闭 cornjobs 事件,CPU 就会降低到正常值。
我检查了日志文件夹,没有错误或类似的东西。
有人遇到过这种情况吗?有没有人知道该如何解决这个问题?谢谢您的帮助!
附言:我们有另一款产品,它不是通过命令行执行 cronjobs,而是通过“cronjobs”向端点发出 HTTP 请求。我们在生产中使用了超过 30 个“cronjobs”,但 CPU 使用率远不及这个。
答案1
我猜:因为它们是同时开始的,所以它们可能会创造一些竞争条件或者锁定数据库,导致无法成功完成所有或部分任务。我认为可能只有其中两个任务相互锁定,无法完成。
而且由于每分钟都会启动一项新作业,因此资源(可能是 MySQL)的竞争者越来越多,由于某些锁定,没有一个能够完成其工作。实例上的资源使用率不断上升,最终实例会死亡。
这是我的猜测。
该怎么办:发生这种情况时,请通过 SSH 连接到实例并执行ps -faxu
和/或使用top
来确定哪些 cron 作业仍在运行。您可以从进程名称中判断出来。
下一步是确保有问题的 cron 作业一次只运行一次。
您有几个选择:
简单但可能不太可靠的方法是将 cron 任务分散到每分钟内。例如在前面添加
sleep 10
/sleep 20
/ ...:sleep 10; . /opt/elasticbeanstalk/support/envvars && /var/app/current/bin/cake cronjob_number_one > /var/log/cronjobs_php 2>&1
更好但更复杂一点的方法是使用信号量,例如借助
flock(1)
. 本质上它的工作原理如下:- 你启动 cron 任务
- 它调用
flock
尝试创建一个锁定文件 - 如果成功 ->运行实际作业
- 如果没有(因为旧的仍然存在,因为工作还没有完成)->出口
希望有帮助:)