ts.*_*ts. 14 php linux debugging
我有一个PHP脚本作为一个cron作业运行,广泛使用第三方代码.脚本本身有几千个LOC.基本上它是数据导入/处理脚本.(JSON到MySQL,但它也会产生大量的HTTP调用和一些SOAP).
现在,性能随着时间的推移而降级.使用少量记录(大约100)进行测试时,性能良好,可在10-20分钟内完成.当运行整个导入(大约1600条记录)时,一条记录的平均导入时间稳步增长,整个过程需要超过24小时,因此至少比预期长5倍.
内存似乎不是问题,使用量增长应该没有意外的峰值.
所以,我需要调试它以找到瓶颈.它可能是脚本,底层代码库,php本身,数据库,操作系统或网络部分的一些问题.我现在怀疑某种缓存在某个地方,这种缓存在接近100%的错失率方面表现不佳.
我不能使用XDebug,配置文件增长得太快而无法治疗.
所以问题是:如何调试这种脚本?
PHP版本:5.4.41操作系统:Debian 7.8如有必要,我可以拥有root权限,并安装工具.但它是生产服务器,理想情况下调试不应该太扰乱.
有三件事情会浮现在脑海中:
调试选项#2是最简单的.由于这是作为一个cron作业运行,你echo
在脚本中添加了一堆:
<?php
function log_message($type, $message) {
echo "[{strtoupper($type)}, {date('d-m-Y H:i:s')}] $message";
}
log_message('info', 'Import script started');
// ... the rest of your script
log_message('info', 'Import script finished');
Run Code Online (Sandbox Code Playgroud)
然后管道stdout
到cron job命令中的日志文件.
01 04 * * * php /path/to/script.php >> /path/to/script.log
Run Code Online (Sandbox Code Playgroud)
现在,您可以添加log_message('info|warn|debug|error', 'Message here')
整个脚本,至少可以了解性能问题的位置.
调试选项#3只是MySQL中的直接调查工作.您的一个查询可能需要很长时间,并且它可能会出现在MySQL的长期运行查询实用程序中.
用于strace
从系统角度查看程序基本上正在执行的操作.是否挂在IO操作等?strace
应该是遇到任何类型的Linux应用程序的性能问题时尝试的第一件事.没人能躲避它!;)
如果您发现该节目在网络相关的调用像挂起connect
,readfrom
和朋友,这意味着网络通信并挂在某个点,同时连接或等待响应比你可以使用tcpdump
来分析这一点.
使用上述方法,您应该能够找到最常见的性能问题.需要注意的是,你甚至还可以连接到正在运行的任务与strace
使用-p PID
.
如果上述方法没有帮助,我会使用xdebug来分析脚本.您可以使用类似工具分析探查器输出KCachegrind
有一个名为Blackfire的PHP分析工具,目前处于公开测试阶段.有关如何配置CLI应用程序的特定文档.收集配置文件后,您可以在一个漂亮的用户界面中通过时间测量来分析应用程序控制流:
内存似乎不是问题,使用量增长应该没有意外的峰值.
不断增长的内存使用率听起来很可疑!如果当前数据集不依赖于导入的所有先前数据集,那么增长的内存很可能意味着所有导入的数据集都保存在内存中,这很糟糕.PHP也可能经常尝试垃圾收集,只是为了发现没有什么可以从内存中删除.特别是长时间运行的CLI任务会受到影响,因此请务必阅读发现该行为的博客文章.
虽然没有规定,如果我的猜测是正确的,你似乎一次只处理一个记录,但是在一个大的cron中.
即抓住一个记录#1,以某种方式捣乱它,为它增加价值,重新格式化然后保存它,然后移动到记录#2
我会考虑打破这个大cron.即
Cron#1:获取所有记录,并在本地缓存所有显着数据(到该服务器).如果达到此阶段,请设置标志.
Cron#2:现在你拥有了你需要的数据,munge和add value,缓存那个输出.如果达到此阶段,请设置标志.
Cron#3:重新格式化数据并存储它.删除所有文件.
这种"分而治之"将缓解你的调试困境,并导致更好地了解实际发生的事情,并作为奖励让你有机会重新运行说,cron 2.
我必须多次这样做,对我而言,日志记录是识别代码中的弱点,识别关于数据质量的不良假设的关键,并且可以暗示延迟导致问题的位置.