日期:2014-05-16  浏览次数:20689 次

对epoll+多线程的用法和效率的疑问,麻烦高手指点!
各位兄弟,我最近才开始接触epoll,现在正在看我们公司一个老员工的代码。该程序主要有如下几个部分:
1.网络接入层封装成了一个class   Poll,负责epoll_create,listen和监听EPOLLIN,EPOLLOUT等事件(ET模式)
2.然后一旦从客户端收到(recv)了数据以后,将其构造成一个消息,放入消息队列中
3.若干工作线程竞争,从消息队列中取出消息并进行处理,然后把处理结果发送(send)给客户端。

我的问题在这里:
1)上面的流程中,工作线程处理完了消息以后是直接使用send来发送结果的,并没有判断这个连接是否处于EPOLLOUT状态,这样会有什么问题吗?
2)如果上述的流程有问题,那么我想到的解决方案就是将处理结果丢给负责网络接入的线程(就是上面第一点说道的那个class对应的线程)。那么因为所有的网络收包和发包都由同一个线程来处理,会不会存在性能问题,甚至影响到新的连接的接入或者其它?
3)如果由同一个线程处理网络方面的收发包存在性能问题,有没有好的办法解决呢?

这个问题我考虑了一天,还是没有考虑清楚,恳请各位高手指点。

------解决方案--------------------
不太了解epoll,不过以前用听起来与经典的accept-fork方式有些类似。
1. 没有问题,决大多数情况下连接EPOLLOUT是成立的,例外的情况通常是线程处理消息时客户中断了连接,这也不存在什么问题,会立即返回失败。
2. 两个问题都存在。
3. 用楼主开在开头提到的方法。
------解决方案--------------------
1. 新建的socket 默认是可写状态的, 如果send出错, socket肯定是有问题了
2. 基本上没有问题. 但可提供了另外一种解决方案, 接入层和 业务处理层可以分开(分进程,分机器)
3. 接入层只负责向客户端收发包, 再组包(包里有head结构,结构中有接入层的IP和端口,客户端的IP和端口,一个序列员)发给业务处理层, 业务处理层处理完后回包给接入层

流程:
client ---> interface ----> 业务处理层 --- > interface ---> client
interface ----> 业务处理层 --- > interface 是内网操作, 速度很快.

------解决方案--------------------
1.在发送大量数据的情况下(超过几百KB), 肯定有问题, 但可以通过write的
返回值和errno检测出来(write返回-1, errno为EAGAIN)

但由于客户端的数据已经接收完, 那么好象得把EPOLLOUT事件加到事件监听
队列中, 等到下一次epoll_wait返回时再接着写此socket

不知道这种说法/做法对不对, 期待高手回答...