1
reusFork 2014-09-11 11:03:45 +08:00 1
epoll是用来通知io事件的,和线程无关,和上下文切换也无关。线程的上下文切换也不会产生10秒的差别。epoll不是选举算法,等待io时切换,那是协程负责的工作。
没有具体的代码,没人可以帮你定位bug。 |
2
pyKun OP @reusFork
怀疑到 epoll 是因为,用 python 的 trace 模块追踪 server 这块的时候,发现消耗时间最多的是: .... 56.894 .... {method 'poll' of 'select.epoll' objects} 56秒那个是这段测试时间,跑 select.epoll.poll 这里总的消耗时间(平均的 * 次数) 在并发5,请求 100 次的时候 epoll.poll 一共消耗了 56 秒 但是顺序请求 100 次的时候,这里只有 3 秒多(另外一个不同时,这个方法被 call 的次数在鬓发的时候 2w 到 4w 不等,顺序的时候,只有 1w;平均消耗时间,并发的时候是 0.03s,顺序的时候 0.00s 就是小于 0.005s) (上文的 25s ~ 35s 只是举例子) 另外,select 模块的位置是 /usr/lib64/python2.6/lib-dynload/selectmodule.so rpm -qf 这个文件发现这个位置的文件是来自于 python-libs 这个包 以上均是客观事实了,能帮我小分析下么 :) |
3
pyKun OP |
4
nybux 2014-09-11 12:30:35 +08:00 1
适合epoll,但是不适合你这样做,mysql调用要调度到一个线程池里面。或者你用pymysql+gevent,把mysql的netio也异步化
|
5
pyKun OP |
6
mucid 2014-09-11 13:18:40 +08:00
mysql得用异步驱动才行
|
7
dafang 2014-09-11 13:24:26 +08:00
连接MySQL的地方,改用nonblocking的库...
|
8
nybux 2014-09-11 14:31:42 +08:00
你现在的瓶颈在于mysql请求,虽然通过eventlet可以在单线程中并发处理大量请求,但是因为整个程序是单线程的。所以,所有的mysql处理最终还是会排队执行。整个程序的吞吐量就是取决于你的单线程执行mysql的效率。所以把mysql请求放到线程池中,就能缓解状况。
|
9
leyle 2014-09-11 18:44:49 +08:00 via Android
100次顺序请求都要耗时25秒,首先需要解决的是单次请求的耗时吧,服务端从接到请求到处理完毕,单次千分之一秒的耗时我觉得还算能接受
|
10
leyle 2014-09-11 18:47:45 +08:00 via Android
并且你对 epoll 的理解是错的,如果想深入正经的理解几种无阻塞 I/O 模型,可以参考 the linux programming interface 64章的内容
|
11
pyKun OP @leyle
100次请求是实际的,25s和35s是在主贴里大概描述的,顺序的情况下都0.02s左右完成,再优化是之后的任务了,不过千分之一秒这个目标不错,自己之前没啥概念 我遇到的问题还是如之前所说,并发的时候(哪怕并发只有5)会出现诡异情况: 1. 0.2s 2. 0.2s 3. 15s 4. 0.2s ... python的trace结果是select.epoll.poll总耗时太长(顺序的总耗时3s左右,5并发100总请求的情况都有50s了) 正在用大家意见调整mysql到nonblocking再测 |
12
mengskysama 2014-09-12 09:09:04 +08:00
你这个业务流程就是顺序执行嘛,为啥会用epool。worker模式不用epool,参照php cgi。
异步数据库处理时间不会比现在少,空转和异步cb的时间应该是相当的。 先查查是不是数据库是不是有锁表,还有数据库是不是有连接数或者性能上限制。 |
13
pyKun OP |