对epoll+多线程的用法和效率的疑问,麻烦高手指点!

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

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

这个问题我考虑了一天,还是没有考虑清楚,恳请各位高手指点。
...全文
2254 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
notebook2001a 2009-02-25
  • 打赏
  • 举报
回复
如果只用一个线程来处理向客户发送的话,又只用阻塞的话,很有可能导致基个写过程阻塞在那里不动.
mauricewoo 2007-07-05
  • 打赏
  • 举报
回复
欢迎讨论
umbrella1984 2007-07-05
  • 打赏
  • 举报
回复
为每个客户发送数据单独用一个线程,然后用阻塞的方式传输。
redex 2007-07-05
  • 打赏
  • 举报
回复
雨伞兄:
假如服务器是类似ftp或流媒体类的服务器(服务器需要长时间传输, 而客户端只需要
发一个命令即可), 这样的话, 如果客户端处理速度较慢,或网络速度较慢...etc, 那么
服务器端针对这个socket的写操作大约就是写几十k数据后就返回-1了(errno=EAGAIN),

如果是单线程服务器模型的话, 难道你要针对这个特定的客户端等几秒 再发送数据???
redex 2007-07-04
  • 打赏
  • 举报
回复
to楼主: 我说得就是监听服务器端"可写"事件啊!

这种问题需要实践, epoll方面的文档/例子写得太笼统, 基本没什么参考价值
一定要动手啊!!!
umbrella1984 2007-07-04
  • 打赏
  • 举报
回复
EPOLLOUT事件我觉得不需要监听,如果连接正常永远是可写的。而且这个事件基本上是随机的,你监听到这个事件也不一定有数据要发。
mauricewoo 2007-07-03
  • 打赏
  • 举报
回复
感谢楼上各位的答复,但是感觉大伙都是针对短连接,一问一答模式的。呵呵。
不如我提一个比较具体,非一问一答模式,但是又有一定的现实意义的问题吧:
比如说,做一个游戏大厅服务器GameServer。
那么这个GameServer所连接的client肯定很多,并且都是长连接。假定客户端有如下的需求:
1登录,2退出,3改名字和4获取大厅中所有用户的名字
如果说按照我的想法,那么应该是这样:
class Epoll是一个单独的线程,负责网络接入,监听EPOLLIN|EPOLLOUT|EPOLLET
收到client的数据以后,构造成消息传给Worker线程。
Worker线程处理消息,并将结果通知需要通知的人。(比如当新用户登录的时候,需要给这个新用户返回(send)一个确认,同时需要给大厅里的所有老用户告知(send)有新的用户登录。)

在这种方式下,并不是所有的网络交互都交给Epoll对应的那个线程处理,所以性能可能会好一点。但是认真考虑这个方式,发现Epoll线程其实仅仅是负责监视EPOLLIN事件和接收,所有的send都是由Worker线程处理的。
这么做可以的吗?

期待高手们的指点。
mauricewoo 2007-07-03
  • 打赏
  • 举报
回复
再顶一下,期待更多高手的回复。呵呵
mymtom 2007-07-03
  • 打赏
  • 举报
回复
不太了解epoll,不过以前用听起来与经典的accept-fork方式有些类似。
1. 没有问题,决大多数情况下连接EPOLLOUT是成立的,例外的情况通常是线程处理消息时客户中断了连接,这也不存在什么问题,会立即返回失败。
2. 两个问题都存在。
3. 用楼主开在开头提到的方法。
redex 2007-07-03
  • 打赏
  • 举报
回复
1.在发送大量数据的情况下(超过几百KB), 肯定有问题, 但可以通过write的
返回值和errno检测出来(write返回-1, errno为EAGAIN)

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

不知道这种说法/做法对不对, 期待高手回答...
mauricewoo 2007-07-03
  • 打赏
  • 举报
回复
自己顶一下
poemdreamer 2007-07-03
  • 打赏
  • 举报
回复
1. 新建的socket 默认是可写状态的, 如果send出错, socket肯定是有问题了
2. 基本上没有问题. 但可提供了另外一种解决方案, 接入层和 业务处理层可以分开(分进程,分机器)
3. 接入层只负责向客户端收发包, 再组包(包里有head结构,结构中有接入层的IP和端口,客户端的IP和端口,一个序列员)发给业务处理层, 业务处理层处理完后回包给接入层

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

23,121

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧