超时问题调研

我们的消息中间件,要在每个通信的机器上启一个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设成高优先级不能解决问题——优先级虽高,但终究是要睡的。

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


相关文章

分类

9 Comments

dutor said:

很复杂的东西

tos said:

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

DongHao Author Profile Page said:

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

ip2004 said:

不知道这个问题最终的原因是不是进程切换的问题?
linux里面高优先级的线程不会抢占吗?

DongHao Author Profile Page said:

阁下点中要害了,仔细想来,确实是只要有进程切换就会超时,跟优先级高低似乎没有关系。

ip2004 said:

请问DongHao兄这个问题最终查出的原因是预想的那样吗?Linux内核不能抢占吗?

DongHao Author Profile Page said:

Linux内核肯定是能抢占的,目前为止我怀疑的可能是:
1. rhel5的老调度算法给高优先级进程的优先度不够
或者:
2. 只要进程切换,必然就拖慢

可以安装新的内核或改用bfs patch来验证第一条怀疑,但是一直没时间再弄了。
以后再抽空。

ip2004 said:

记不起来是搜什么东西的时候看到这个文章了,没想到随手问了一下,DongHao兄就回复了。

我是做嵌入式方面的,接触的都是一些RTOS,所以考虑的角度可能和DongHao兄不一样:

1 linux的tick是10ms,php设置3ms超时,也就是说当前请求发出后,如果下一个被调度运行的不是daemon的话,就超时了;当然4核的情况下如果可以在其他的核上执行daemon,不会发生超时。如果所有的核都被占用了呢?这个时候就和抢占以及优先级有关了。
2 如果在一个rtos里,daemon的优先级高,那么只有daemon ready,它马上就可以打断其他的任务得到CPU(当然其他任务不能在执行临界代码),和上面说的有空闲的cpu其实差不多。

linux我只是了解,它的任务优先级和抢占是什么样的策略我不知道,下面的是猜测:
3 php请求daemon的服务之后是sleep了吗?如果是的,应该会引起重新调度,这个时候如果daemon的优先级高,应该会在调度中得到cpu而运行,应该也不会超时;
4 如果php请求daemon服务之后没有sleep,而linux的抢占又不是那种“rtos式”的抢占,很可能daemon还没运行的时候php那边已经“等得不耐烦”(超时)了……

DongHao Author Profile Page said:

感谢ip2004兄的分析,看来细节还有很多啊。。。

留言:

关于文章

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.