关于eventmachine的timeout
工作中负责实现thrift的eventmachine客户端版本,在实现过程中就遇到了读写timeout如何实现的问题.
eventmachine的connection有两个连接的参数pending_connect_timeout
和comm_inactivity_timeout
,但就是没有read和write的timeout的配置参数,这样的话,业务调用就没有超时,根本不能够在线上使用.
后来发现em有Timer
功能,那么就在每次调用read的时候,同时初始化一个Timer
,利用Timer
来控制超时.
1 | def read(size,timeout) |
经过测试,这个方案还是可以的,我本来以为这样会增加CPU的消耗,但是测试并没有发现CPU占用有增长(应该是em的轮询线程就一个mainloop的原因,Timer多了只是增加了轮询的个数),就是每次都会初始化一个Timer
对象,感觉有点坑爹.但是也没有什么好办法,而且后来发现Thrift官方的EM支持就是这个方案来设置超时的,所以就在线上使用了.
后来和老大讨论了这个问题,老大也觉得挺坑爹,给我一个建议,能否使用Period_Timer
,他发现Java的so_timeout不是设置SO_RCVTIMEO实现的,见SocketInputStream.c,其中使用了NET_timeout函数,感觉上像是循环调用select/poll的api,如果在timeout时间范围内fd还不是readable,那么就超时,否则读数据(不过这样我就不明白如何确定数据读完).
通过这个问题,感觉自己有时间得去看看epoll/kqueue/select/poll等unix网络相关的内容.以后会记录这个问题的详细研究结果.