在Centos 5上缓慢的cron工作

时间:2011-10-25 18:46:29

标签: php mysql apache cron overlap

我有一个每60分钟运行一次的cronjob,但由于某种原因,最近它运行缓慢。

环境:centos5 + apache2 + mysql5.5 + php 5.3.3 / raid 10 / 10k HDD / 16gig ram / 4 xeon处理器

这是cronjob的作用:

  1. 解析最后60分钟的数据

    a)1个进程解析用户代理并将数据保存到数据库

    b)1个流程解析网站上的展示次数/点击次数并将其保存到数据库

  2. 来自步骤1中的数据

    a)建立一个小报告并向管理员/商务发送电子邮件

    b)将报告保存到每日表格(可在管理部分中找到)

  3. 当我运行命令ps auxf | grep process_stats_hourly.php(在stackoverflow中找到此命令)时,我现在看到8个进程(同一个文件)

    从技术上讲,我应该只有1而不是8。

    Cent OS中是否有任何工具可以确保我的cronjob每小时运行一次而不会与下一个重叠?

    由于

7 个答案:

答案 0 :(得分:46)

您的硬件似乎足以处理此问题。

1)检查您是否已挂起进程。使用ps auxf(请参阅tcurvelo答案),检查是否有一个或多个进程占用了太多资源。也许你没有足够的资源来运行你的cronjob。

2)检查您的网络连接: 如果您的数据库和您的cronjob位于不同的服务器上,您应该检查这两台计算机之间的响应时间。也许你有网络问题让cronjob等待网络发回包。

您可以使用:NetcatIperfmtrttcp

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

保持循环,直到命令没有返回任何内容,表明进程没有运行,然后允许剩余的代码执行。