比如 100 个客户端,连接到了服务器,然后都停止操作, epoll 好处就是一个进程(线程)就可以 hold 住 100 个连接,而不用创建 100 个进程或线程由操作体统来切换上下文,给每个线程都分一点时间,而是当有客户端传送过来数据的时候,阻塞结束可以进行下一步操作,伪代码:
for loop
# 阻塞等待 100 个客户端返回一个可读的 socket
# def dosomething
问题是如果在 do something 里进行数据库连接等费时间的 io 操作,响应时间依然感人啊。。。
比如两个人并发访问,第一个人 do something,花了三秒(io 操作),下一个用户就得等三秒才开始为他服务,,,,
我的理解是否有错误?解决do something
里面 io 时间的又是什么技术?我大概觉得能用 gevent ( io 阻塞的时候 yield 到其他协程),但是想不明白具体是怎么做的,有什么文章或者书吗?谢谢大家。
1
SErHo 2016-07-31 17:15:23 +08:00 1
"进行数据库连接等费时间的 io 操作" 也就是说你在“异步”(姑且叫异步吧,其实是事件循环)里面进行了耗时的同步 IO 操作,这是错误的。。。
解决方法就是把这个数据库同步 IO 操作改成异步的,加入到你主体的事件循环里面,问题是很麻烦做到,有时候不可能,想想在 tornado 里面做数据操作的时候,这就是为什么有那么多针对 tornado 数据库操作的库,如 https://github.com/PyMySQL/Tornado-MySQL 。 所以需要 gevent 或者 golang 这种在框架或语言底层自动将 IO “异步”化(多路复用)的技术。 |
2
petelin OP @SErHo 确实是`事件循环`,那就是说我对这种服务器框架的理解还是对的,单个线程就是通过死循环一个一个的处理请求。
在时间循环里进行异步 io ,,,(⊙o⊙)…我小小的脑子想不出来改怎么调度啊,,,先处理 触发的事件呢,还是先处理 回调的事件呢,他怎么知道回调的函数改执行了,这都是在一个线程里啊 |
3
SErHo 2016-07-31 17:52:43 +08:00
@petelin 所以说做到很麻烦啊,要进行详尽的规划和拆分,你看看 Nginx 的 upstream 相关的模块那代码写的是多蛋疼,回调过去回调过来的,这就是为啥业务复杂了还是用协程(gevent, golang) 这类的爽。
|
4
akira 2016-07-31 18:04:25 +08:00
理解没问题,所以 dosomething 里面尽量不要有耗时的操作
|
5
oska874 2016-07-31 18:55:10 +08:00
dosomething 里再启个线程?
|
6
julyclyde 2016-07-31 23:11:30 +08:00
socket 可以是 NONBLOCKING 的啊
为什么你认为必须阻塞? |
8
IwfWcf 2016-08-01 02:48:08 +08:00 via iPhone
协程大法好
|