Centos 5 上的慢 cron 作业
Posted
技术标签:
【中文标题】Centos 5 上的慢 cron 作业【英文标题】:Slow cronjobs on Cent OS 5 【发布时间】:2011-12-15 04:59:24 【问题描述】:我有 1 个每 60 分钟运行一次的 cronjob,但由于某种原因,最近它运行缓慢。
环境:centos5 + apache2 + mysql5.5 + php 5.3.3 / raid 10/10k HDD / 16gig ram / 4 xeon 处理器
这是 cronjob 的作用:
解析最近 60 分钟的数据
a) 1 个进程解析用户代理并将数据保存到数据库
b) 1 个进程解析网站上的展示次数/点击次数并将其保存到数据库中
来自步骤 1 中的数据
a) 建立一个小报告并向管理员/企业发送电子邮件
b) 将报告保存到每日表格中(在管理部分可用)
当我运行命令 ps auxf | grep process_stats_hourly.php
(在 *** 中找到此命令)时,我现在看到了 8 个进程(同一个文件)
从技术上讲,我应该只有 1 个而不是 8 个。
Cent OS 中是否有任何工具或我可以做些什么来确保我的 cronjob 每小时运行一次并且不会与下一个重叠?
谢谢
【问题讨论】:
你看到了 8 个。你确定前7个成功完成了吗?你能看到数据库中的数据逐渐减少(如果你刷新,你会看到这个过程仍在积极工作吗?)? 【参考方案1】:您的硬件似乎足以处理这个问题。
1) 检查您是否已经有挂起的进程。使用ps auxf
(参见 tcurvelo 答案),检查您是否有一个或多个进程占用过多资源。也许你没有足够的资源来运行你的 cronjob。
2) 检查您的网络连接: 如果您的数据库和您的 cronjob 在不同的服务器上,您应该检查这两台机器之间的响应时间。也许你有网络问题导致 cronjob 等待网络将包发回。
您可以使用:Netcat、Iperf、mtr 或 ttcp
3) 服务器配置 你的服务器配置正确吗?您的操作系统、MySQL 设置正确吗?我建议阅读这些文章:
http://www3.wiredgorilla.com/content/view/220/53/
http://www.vr.org/knowledgebase/1002/Optimize-and-disable-default-CentOS-services.html
http://dev.mysql.com/doc/refman/5.1/en/starting-server.html
http://www.linux-mag.com/id/7473/
4) 检查您的数据库: 确保您的数据库具有正确的索引并确保您的查询得到优化。阅读这篇关于explain command的文章
如果一个包含几十万条记录的查询需要花费一些时间来执行,这将影响你的 cronjob 的其余部分,如果你有一个循环内的查询,那就更糟了。
阅读这些文章:
http://dev.mysql.com/doc/refman/5.0/en/optimization.html
http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/
http://blog.fedecarg.com/2008/06/12/10-great-articles-for-optimizing-mysql-queries/
5) 跟踪和优化 PHP 代码? 确保您的 PHP 代码尽可能快地运行。
阅读这些文章:
http://phplens.com/lens/php-book/optimizing-debugging-php.php
http://code.google.com/speed/articles/optimizing-php.html
http://ilia.ws/archives/12-PHP-Optimization-Tricks.html
验证您的 cronjob 的一个好方法是跟踪您的 cronjob 脚本: 根据您的 cronjob 进程,放置一些调试跟踪,包括多少内存、执行最后一个进程所花费的时间。例如:
<?php
echo "\n-------------- DEBUG --------------\n";
echo "memory (start): " . memory_get_usage(TRUE) . "\n";
$startTime = microtime(TRUE);
// some process
$end = microtime(TRUE);
echo "\n-------------- DEBUG --------------\n";
echo "memory after some process: " . memory_get_usage(TRUE) . "\n";
echo "executed time: " . ($end-$start) . "\n";
通过这样做,您可以轻松找到哪个进程占用了多少内存以及执行它需要多长时间。
6) 外部服务器/网络服务调用 您的 cronjob 是调用外部服务器还是 Web 服务?如果是这样,请确保尽可能快地加载这些内容。如果您从第三方服务器请求数据,并且该服务器需要几秒钟来返回一个答案,这将影响您的 cronjob 的速度,特别是如果这些调用处于循环状态。
试试看,然后告诉我你发现了什么。
【讨论】:
调试代码后,我们发现主 cronjob 服务器和我们正在使用的第三方soap web 服务之间存在延迟。每小时我们需要汇总的记录超过 150,000 条,而这个调用的执行时间太长(每次调用平均需要 2 到 4 秒)。几个小时后,我们找到了解决此问题的方法。我们还使用您提供的命令对我们的服务器进行了一些优化。非常感谢您的帮助【参考方案2】:ps
的输出还显示进程何时开始(参见列STARTED
)。
$ ps auxf
USER PID %CPU %MEM VSZ RSS TTY STAT STARTED TIME COMMAND
root 2 0.0 0.0 0 0 ? S 18:55 0:00 [ktrheadd]
^^^^^^^
(...)
或者你可以自定义输出:
$ ps axfo start,command
STARTED COMMAND
18:55 [ktrheadd]
(...)
因此,您可以确定它们是否重叠。
【讨论】:
【参考方案3】:您应该在您的 process_stats_hourly.php 脚本中使用锁定文件机制。不必过于复杂,您可以让 php 将启动进程的 PID 写入 /var/mydir/process_stats_hourly.txt 之类的文件。因此,如果处理统计数据的时间超过一个小时,并且 cron 启动了 process_stats_hourly.php 脚本的另一个实例,它可以检查锁定文件是否已经存在,如果存在则不会运行。
但是,如果每小时脚本确实找到了锁定文件并且无法启动,您将面临如何“重新排队”的问题。
【讨论】:
【参考方案4】:您可以在其中一个运行时间过长的进程上使用strace -p 1234
,其中 1234 是相关的进程 ID。也许你会明白为什么它这么慢,甚至被阻塞。
【讨论】:
【参考方案5】:Cent OS 中是否有任何工具或我可以做些什么来确保我的 cronjob 每小时运行一次并且不会与下一个重叠?
是的。 CentOS 的标准util-linux
软件包为文件系统锁定提供了命令行便利。正如 Digital Precision suggested,锁文件是同步进程的一种简单方法。
尝试按如下方式调用您的 cronjob:
flock -n /var/tmp/stats.lock process_stats_hourly.php || logger -p cron.err 'Unable to lock stats.lock'
您需要编辑路径并根据需要调整 $PATH。该调用将尝试锁定stats.lock
,如果成功则生成您的统计脚本,否则放弃并记录失败。
或者,您的脚本可以调用 PHP 的 flock() 本身来实现相同的效果,但 flock(1)
实用程序已经为您准备好了。
【讨论】:
【参考方案6】:该日志文件多久轮换一次?
日志解析工作突然比平时花费更长的时间,听起来好像日志没有被轮换,而且现在对于解析器来说太大而无法有效处理。
尝试重置日志文件,看看作业是否运行得更快。如果这样可以解决问题,我建议使用logrotate 作为防止将来出现问题的方法。
【讨论】:
【参考方案7】:您可以在 cronjob 中添加一个步骤来检查上述命令的输出:
ps auxf | grep process_stats_hourly.php
继续循环,直到命令没有返回任何内容,表明进程没有运行,然后让剩余的代码执行。
【讨论】:
这并不能解决问题,只能延迟它以上是关于Centos 5 上的慢 cron 作业的主要内容,如果未能解决你的问题,请参考以下文章