我有一个每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
(在stackoverflow中找到此命令)时,我现在看到8个进程(同一个文件)
从技术上讲,我应该只有1而不是8。
Cent OS中是否有任何工具可以确保我的cronjob每小时运行一次而不会与下一个重叠?
由于
答案 0 :(得分:46)
您的硬件似乎足以处理此问题。
1)检查您是否已挂起进程。使用ps auxf
(请参阅tcurvelo答案),检查是否有一个或多个进程占用了太多资源。也许你没有足够的资源来运行你的cronjob。
2)检查您的网络连接: 如果您的数据库和您的cronjob位于不同的服务器上,您应该检查这两台计算机之间的响应时间。也许你有网络问题让cronjob等待网络发回包。
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速度的答案,特别是如果这些调用是循环的。
试一试,让我知道你发现了什么。
答案 1 :(得分:6)
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]
(...)
因此,您可以确定它们是否重叠。
答案 2 :(得分:4)
您应该在process_stats_hourly.php脚本中使用lockfile机制。不必过于复杂,你可以让php将启动过程的PID写入/var/mydir/process_stats_hourly.txt这样的文件。因此,如果处理统计信息需要花费一个多小时,而cron将启动process_stats_hourly.php脚本的另一个实例,它可以检查锁文件是否已经存在,如果存在则不会运行。
但是,如果它确实找到了锁定文件并且无法启动,那么您将面临如何“重新排队”每小时脚本的问题。
答案 3 :(得分:2)
您可以在其中一个运行时间过长的进程中使用strace -p 1234
,其中1234是相关进程ID。也许你会明白为什么它如此缓慢,甚至被阻挡。
答案 4 :(得分:2)
在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)
实用程序已经存在。
答案 5 :(得分:0)
该日志文件多久轮换一次?
日志解析作业突然花费比平常更长的时间,如日志没有被旋转,现在太大了,解析器无法有效处理。
尝试重置日志文件并查看作业是否运行得更快。如果这样可以解决问题,我建议logrotate作为将来防止问题的一种方法。
答案 6 :(得分:-1)
您可以在cronjob中添加一个步骤来检查上述命令的输出:
ps auxf | grep process_stats_hourly.php
保持循环,直到命令没有返回任何内容,表明进程没有运行,然后允许剩余的代码执行。