首页 / PHP / 记一次php高负载问题排查经历
记一次php高负载问题排查经历
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了记一次php高负载问题排查经历,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3412字,纯文字阅读大概需要5分钟。
内容图文
![记一次php高负载问题排查经历](/upload/InfoBanner/zyjiaocheng/203/3c90545f189c452db9f83ccc0babb932.jpg)
第一步先使用strace查看系统调用情况:
strace -tt -T -c -p 31420
strace -c发现,系统时间主要耗费在rt_sigprocmask上,该函数是系统的信号屏蔽函数,一般使用在信号处理程序中,对信号进行屏蔽,保证信号处理程序不被打断。rt_sigprocmask为linux的系统调用函数,不对外直接调用,而使用glibc对其的封装:sigprocmask.
进一步starce调用实际情况:
rt_singprocmask调用有一个特征:设置屏蔽字后紧接着恢复屏蔽字,可以联想到这有可能php的信号处理函数中调用的。
在php源码中搜索sigprocmask,发现php源码中调用singprocmask的地方主要在pnctl扩展中,在deamon程序使用了pnctl扩展创建和管理子进程。通过先阻塞信号后恢复信号的特征,定位到php的信号处理函数:pcntl_signal_dispatch()中。
接着通过加日志验证我们的想法,确认确实在频繁调用该函数。由此引出了对php信号处理机制的分析。
限于篇幅,具体分析过程省略,这里给出分析的结果:
- php的tick机制:
phpmanul对tick的解释是:
A tick is an event that occurs for every N low-level tickable statements executed by the parser within the declare block. The value for N is specified using ticks=N within the declare block's directive section.
Not all statements are tickable. Typically, condition expressions and argument expressions are not tickable.
The event(s) that occur on each tick are specified using the register_tick_function(). See the example below for more details. Note that more than one event can occur for each tick.
大概意思是:tick和register_tick_function配合,每执行tick=n的n个底层指令,就触发执行register_tick_function注册的事件。
2. php对信号的处理:
Php对进程和信号的管理控制通过pcntl扩展实现,pcntl使用了tick机制作为signal的callback机制,你可以在php中允许callback的地方使用declare允许callback发生。
通过对pcntl源码分析,pcntl的信号处理机制是这样的:
1),信号注册
2),信号处理:
分析到这里,可以看到:在php中,根据declare声明的tick值来定期调用,当tick值配置较低时(本程序中定义ticks=1),会大量触发信号处理程序,该程序中调用rt_sigprocmask导致浪费大量的cpu,机器负载变高。
那么php为什么要采用这种信号处理机制呢?
查看在php manual时,发现这样的介绍:
PCNTL now uses ticks as the signal handle callback mechanism, which is much faster than the previous mechanism. This change follows the same semantics as using "user ticks". You use the declare() statement to specify the locations in your program where callbacks are allowed to occur. This allows you to minimize the overhead of handling asynchronous events. In the past, compiling PHP with pcntl enabled would always incur this overhead, whether or not your script actually used pcntl.
重点关注:You use the declare() statement to specify the locations in your program where callbacks are allowed to occur. 意思是可以指定需要捕获信号的代码区域,区域外则不进行信号处理。
由上可以总结出修改问题的办法:
1),通过declare制定应用程序捕捉信号的区域,
2),对于不需要进行信号处理的程序,不声明declear(ticks=n),由此不会触发调用信号处理程序;需要处理的程可以手动调用信号处理程序pcntl_signal_dispatch代替php的定时检测。
经过验证,采用以上任何一种办法都可以解决问题。机器负载降到正常值。
总结:
1),php采用类似linux内核中断处理机制(硬中断+软终端)机制处理信号,需要注意检测信号的频次,避免cpu性能浪费。
2),因为在cgi中不建议使用pcntl扩展管理创建进程,该机制不会对webserver的cgi产生影响
内容总结
以上是互联网集市为您收集整理的记一次php高负载问题排查经历全部内容,希望文章能够帮你解决记一次php高负载问题排查经历所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。