超时问题调研

我们的消息中间件,要在每个通信的机器上启一个daemon,负责转发。我们还为这个中间件开发了php接口(尽管我并不看好php,但它毕竟是前端的常用语言)。

在 处理业务部门反馈的问题时,发现一个奇特的现象:php程序通过中间件收发消息,设置是3ms超时,运行正常,没有超时的消息;但如果在php里加一个循 环(加循环的位置与中间件的调用无关),超时出现了。php自己傻循环怎么会影响中间件消息的response time呢?

先是怀疑我们的php module写得不对,参考了一下别人的代码,发现没有什么特别的,用的是极简单的php module API,如果这样写都不对,真不知道什么是对的了。

再 是怀疑php本身,于是换了几个php版本(php接口也要重新编译,累人),问题依然出现。再把我们的中间件API加入php的 basic_function里,即做为php的内置函数(就像split,sleep这些函数一样),问题还是一样。可能不是php的问题。

接着怀疑apache,于是降低apache的进程数,发现httpd进程数为1或2的时候真的没有超时了,但进程数如果多于3就不行。难道apache的调度有问题?我们默认用的是prefork任务模式,换成worker试试(参见这里),换mpm了,php给apache的so也要重新编译(还是累人),最后发现换成worker任务内模式当进程数多了还是一样超时。

难道和php、apache都没有关系?干脆启动两个独立的php进程,没有超时;启动3个,没有超时;启动4个,超时来了。看来4这个数字很神秘。最后猜测是机器乃4核CPU,4个php进程占完了4个CPU,中间件daemon就没有保障了。

这个猜测有点跳跃,要想办法证明之,于是想到了CPU affinity,我们用taskset把4个php进程都绑定到0,1,2三个CPU上,此时超时消失了。看来之前确实是php进程占了4个CPU,导致中间件daemon无法足够快的分配到CPU。

解决方案呢?

如果我改改daemon,是不是能解决这个问题?于是把daemon的优先级设为最高(RT),超时依旧。

仔 细想想有了个结论:daemon用的CPU并不多,但是其睡眠和唤醒非常频繁(daemon主要是IO操作,转发来自网络的包),当其从睡眠中醒来时,必 须很快分配给它一个CPU,但是php占了4个CPU,所以不能很快的给daemon,所以daemon出现了延时(睡过头了),造成消息超时。这大概能 说明为什么把daemon设成高优先级不能解决问题——优先级虽高,但终究是要睡的。

我的结论就是这样,最后的证明还是要看看内核代码了。未完待续。


相关文章

分类

3 Comments

dutor said:

很复杂的东西

tos said:

个人认为, Linux里面10毫秒一个时间片,如果中间没有其他的硬件中断或者主动让出CPU是不可能发生进程切换的。

DongHao Author Profile Page said:

你说的没有错。
但问题在于,我们的daemon要频繁的等待IO,所以进程自己会经常去睡眠。而问题就发生在它醒来的时候——无法每次都快速醒来(当然,目前还是猜测 )。

留言:

关于文章

This page contains a single entry by DongHao published on 04 29, 2010 2:26 PM.

不讨好 was the previous entry in this blog.

大项目不等于大trunk is the next entry in this blog.

Find recent content on the main index or look in the 存档 to find all content.