本文实例讲述了PHP实现通过strace定位故障原因的方法。分享给大家供大家参考,具体如下:

俗话说:不怕贼偷,就怕贼惦记着。在面对故障的时候,我也有类似的感觉:不怕出故障,就怕你不知道故障的原因,故障却隔三差五的找上门来。

十一长假还没结束,服务器却频现高负载,Nginx出现错误日志:

connect() failed (110: Connection timed out) while connecting to upstream

connect() failed (111: Connection refused) while connecting to upstream

看上去是Upstream出了问题,在本例中Upstream就是PHP(版本:5.2.5)。可惜监控不完善,我搞不清楚到底是哪出了问题,无奈之下只好不断重启PHP来缓解故障。

如果每次都手动重启服务无疑是个苦差事,幸运的是可以通过CRON设置每分钟执行:

#/bin/bash

LOAD=$(awk '{print $1}' /proc/loadavg)

if [ $(echo "$LOAD > 100" | bc) = 1 ]; then

/etc/init.d/php-fpm restart

fi

可惜这只是一个权宜之计,要想彻底解决就必须找出故障的真正原因是什么。

闲言碎语不要讲,轮到Strace出场了,统计一下各个系统调用的耗时情况:

shell> strace -c -p $(pgrep -n php-cgi)

% time seconds usecs/call calls errors syscall

------ ----------- ----------- --------- --------- ----------------

30.53 0.023554 132 179 brk

14.71 0.011350 140 81 mlock

12.70 0.009798 15 658 16 recvfrom

8.96 0.006910 7 927 read

6.61 0.005097 43 119 accept

5.57 0.004294 4 977 poll

3.13 0.002415 7 359 write

2.82 0.002177 7 311 sendto

2.64 0.002033 2 1201 1 stat

2.27 0.001750 1 2312 gettimeofday

2.11 0.001626 1 1428 rt_sigaction

1.55 0.001199 2 730 fstat

1.29 0.000998 10 100 100 connect

1.03 0.000792 4 178 shutdown

1.00 0.000773 2 492 open

0.93 0.000720 1 711 close

0.49 0.000381 2 238 chdir

0.35 0.000271 3 87 select

0.29 0.000224 1 357 setitimer

0.21 0.000159 2 81 munlock

0.17 0.000133 2 88 getsockopt

0.14 0.000110 1 149 lseek

0.14 0.000106 1 121 mmap

0.11 0.000086 1 121 munmap

0.09 0.000072 0 238 rt_sigprocmask

0.08 0.000063 4 17 lstat

0.07 0.000054 0 313 uname

0.00 0.000000 0 15 1 access

0.00 0.000000 0 100 socket

0.00 0.000000 0 101 setsockopt

0.00 0.000000 0 277 fcntl

------ ----------- ----------- --------- --------- ----------------

100.00 0.077145 13066 118 total

看上去「brk」非常可疑,它竟然耗费了三成的时间,保险起见,单独确认一下:

shell> strace -T -e brk -p $(pgrep -n php-cgi)

brk(0x1f18000) = 0x1f18000 <0.024025>

brk(0x1f58000) = 0x1f58000 <0.015503>

brk(0x1f98000) = 0x1f98000 <0.013037>

brk(0x1fd8000) = 0x1fd8000 <0.000056>

brk(0x2018000) = 0x2018000 <0.012635>

说明:在Strace中和操作花费时间相关的选项有两个,分别是「-r」和「-T」,它们的差别是「-r」表示相对时间,而「-T」表示绝对时间。 简单统计可以用「-r」,但是需要注意的是在多任务背景下,CPU随时可能会被切换出去做别的事情,所以相对时间不一定准确,此时最好使用「-T」,在行 尾可以看到操作时间,可以发现确实很慢。

在继续定位故障原因前,我们先通过「man brk」来查询一下它的含义:

brk() sets the end of the data segment to the value specified by end_data_segment, when that value is reasonable, the system does have enough memory and the process does not exceed its max data size (see setrlimit(2)).

简单点说就是内存不够用时通过它来申请新内存(data segment),可是为什么呢?

shell> strace -T -p $(pgrep -n php-cgi) 2>&1 | grep -B 10 brk

stat("/path/to/script.php", {...}) = 0 <0.000064>

brk(0x1d9a000) = 0x1d9a000 <0.000067>

brk(0x1dda000) = 0x1dda000 <0.001134>

brk(0x1e1a000) = 0x1e1a000 <0.000065>

brk(0x1e5a000) = 0x1e5a000 <0.012396>

brk(0x1e9a000) = 0x1e9a000 <0.000092>

通过「grep」我们很方便就能获取相关的上下文,反复运行几次,发现每当请求某些PHP脚本时,就会出现若干条耗时的「brk」,而且这些PHP 脚本有一个共同的特点,就是非常大,甚至有几百K,为何会出现这么大的PHP脚本?实际上是程序员为了避免数据库操作,把非常庞大的数组变量通过「var_export」持久化到PHP文件中,然后在程序中通过「include」来获取相应的变量,因为变量太大,所以PHP不得不频繁执行「brk」,不幸的是在本例的环境中,此操作比较慢,从而导致处理请求的时间过长,加之PHP进程数有限,于是乎在Nginx上造成请求拥堵,最终导致高负载故障。

下面需要验证一下推断似乎否正确,首先查询一下有哪些地方涉及问题脚本:

shell> find /path -name "*.php" | xargs grep "script.php"

直接把它们都禁用了,看看服务器是否能缓过来,或许大家觉得这太鲁蒙了,但是特殊情况必须做出特殊的决定,不能像个娘们儿似的优柔寡断,没过多久,服务器负载恢复正常,接着再统计一下系统调用的耗时:

shell> strace -c -p $(pgrep -n php-cgi)

% time seconds usecs/call calls errors syscall

------ ----------- ----------- --------- --------- ----------------

24.50 0.001521 11 138 2 recvfrom

16.11 0.001000 33 30 accept

7.86 0.000488 8 59 sendto

7.35 0.000456 1 360 rt_sigaction

6.73 0.000418 2 198 poll

5.72 0.000355 1 285 stat

4.54 0.000282 0 573 gettimeofday

4.41 0.000274 7 42 shutdown

4.40 0.000273 2 137 open

3.72 0.000231 1 197 fstat

2.93 0.000182 1 187 close

2.56 0.000159 2 90 setitimer

2.13 0.000132 1 244 read

1.71 0.000106 4 30 munmap

1.16 0.000072 1 60 chdir

1.13 0.000070 4 18 setsockopt

1.05 0.000065 1 100 write

1.05 0.000065 1 64 lseek

0.95 0.000059 1 75 uname

0.00 0.000000 0 30 mmap

0.00 0.000000 0 60 rt_sigprocmask

0.00 0.000000 0 3 2 access

0.00 0.000000 0 9 select

0.00 0.000000 0 20 socket

0.00 0.000000 0 20 20 connect

0.00 0.000000 0 18 getsockopt

0.00 0.000000 0 54 fcntl

0.00 0.000000 0 9 mlock

0.00 0.000000 0 9 munlock

------ ----------- ----------- --------- --------- ----------------

100.00 0.006208 3119 24 total

显而易见,「brk」已经不见了,取而代之的是「recvfrom」和「accept」,不过这些操作本来就是很耗时的,所以可以定位「brk」就是故障的原因。

拥抱故障,每一次故障都是历练。正所谓:天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,增益其所不能。

希望本文所述对大家PHP程序设计有所帮助。

strace动态调试 php,PHP实现通过strace定位故障原因的方法相关推荐

  1. xcode 中无法进行虚拟机调试_在软件部署中使用 strace 进行调试

    我最喜欢的用来解决"为什么这个软件无法在这台机器上运行?"这类问题的工具就是 strace. -- Simon Arneaud(作者) 我的大部分工作都涉及到部署软件系统,这意味着 ...

  2. strace命令_在软件部署中使用 strace 进行调试

    我最喜欢的用来解决"为什么这个软件无法在这台机器上运行?"这类问题的工具就是 strace. -- Simon Arneaud(作者) 我的大部分工作都涉及到部署软件系统,这意味着 ...

  3. strace跟踪java,linux运维利器—–strace命令

    strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式 ...

  4. 安卓APP动态调试-IDA实用攻略

    0x00 前言 随着智能手机的普及,移动APP已经贯穿到人们生活的各个领域.越来越多的人甚至已经对这些APP应用产生了依赖,包括手机QQ.游戏.导航地图.微博.微信.手机支付等等,尤其2015年春节期 ...

  5. 如何动态调试Python的第三方库

    如何动态调试Python的第三方库 2017年01月21日 22:53:57 阅读数:1834 注意:本文方法仅限于调试安装时附带py源码的库,如sklearn. 引入 用sklearn中的sklea ...

  6. IDA动态调试技术及Dump内存

    IDA动态调试技术及Dump内存 来源 https://blog.csdn.net/u010019468/article/details/78491815 最近研究SO文件调试和dump内存时,为了完 ...

  7. CLR探索系列:Windbg+SOS动态调试分析托管代码

    http://blog.csdn.net/garyye/article/details/4788070   在使用VS进行托管应用程序的调试的时候,有的时候总感觉有些力不从心.譬如查看一个托管堆或者计 ...

  8. vc2010中开始执行不调试灰的_反编译动态调试smali全过程

    点击上方蓝字关注我,每天进步一点点 大家都知道我们在逆向分析的时候,很多时候主要在分析逻辑.网络抓包.数据来源流向分析.页面逻辑跳转分析.动态调试等.由于很多代码都会混淆,很多时候我们直接通过代码可能 ...

  9. 修改so_新手向总结:IDA动态调试So的一些坑

    本文为看雪论坛优秀文章 看雪论坛作者ID:nisodaisuki 目录 动态调试步骤 复制`android_server`到设备中,并执行. 用`pm`确定要调试apk的包名 用`am`启动被调试应用 ...

最新文章

  1. Windows安全策略
  2. hash集合方法使用
  3. 微服务最佳实践:MSE 微服务引擎
  4. 【渝粤教育】广东开放大学 土地力学与地基基础 形成性考核 (32)
  5. 修改Fiddler实用插件JsonViewer
  6. mysql同表字段前4位复制_MySQL不同表之前的字段复制
  7. DEIGRP 的配置
  8. java中有关类的程序设计_《Java程序设计一》 1,设计课程类及类中包含的属性和方法....
  9. [转]WampServer localhost 图标不显示解决办法
  10. 浙大计算机科学与技术FPGA,Computer Science 计算机科学与技术系 重要国际学术会议...
  11. Java中NumberFormat格式化数字
  12. 利用matlab来进行路径规划,matlab路径规划系列
  13. 硬件安全模块- HSM
  14. HTML5 3D棒球游戏截图
  15. setPositiveButton和setNegativeButton
  16. 交换游戏(状态压缩、记忆化搜索)
  17. python永久配置pip下载镜像源方法(window版本)
  18. UE5 学习2- 快捷键
  19. c语言if语句教学设计,if语句教学设计
  20. 《脚本》Python在线百度文库爬虫(免下载券)

热门文章

  1. Spring AMQP 教程
  2. 行为设计模式 - 命令设计模式
  3. centos 安装oracle java,CentOS 4.4下安装Oracle 10
  4. 【服务端渲染】手动部署 NuxtJs 项目
  5. 【HTML】iframe嵌套界面自适应,可高度自由收缩
  6. C#LeetCode刷题之#40-组合总和 II(Combination Sum II)
  7. C#LeetCode刷题-双指针
  8. golang import中的.和_的使用,import的几种方式点,下划线,别名
  9. 论坛分页频繁更新帖子缓存_如何实现频繁更改内容的“可缓存”分页
  10. facebook 面试_我在Facebook接受了应届毕业生的面试。 这是我从设计中学到的东西。...