求助!!!多线程+多个epoll_wait问题

verylcg 2012-05-10 03:27:31
OS:centos6.2_64
kernel:2.6.32-220.el6.x86_64

主进程先监听端口: bind(...),listen(...)
创建ep: epoll_create, epoll_ctl(...)
创建线多个线程并且都在跑epoll_wait(...) accept4(...)

这么用的原因是在高峰期并发的网络请求非常海量,使得某些排队靠后的socket fd的事件处理不及时。
测试中没有发现惊群现象。
请问这么用有什么问题么?
...全文
769 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
verylcg 2012-05-10
  • 打赏
  • 举报
回复
谢谢,解答的非常清晰
qq120848369 2012-05-10
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 的回复:]

1,不会,早晚会读,只要你仔细检查每一个函数的返回值,肯定会检测出来fd失效。
2,不可以,因为信号量只表示有资源可取,但是并不提供同步功能,有10个connection,结果10个worker同时操作队列,所以你应该懂得。另外一个局限性是原本可以借助条件变量+quit全局变量来方便的cond_brocast令所有worker退出,这在进程支持热重启或者在master-worker模型中试图平……
[/Quote]

2,不是完全不可以,你必须使用两个资源信号量,一个empty,一个full,还需要一个2值信号量用于同步,这就是信号量实现生产者消费者的方法,是需要两个信号量合作的,因为信号量只有0阻塞,而条件变量可以通过编程控制0和满都阻塞,同时条件变量必备的互斥量又提供了同步,这些都是信号量麻烦的地方,不过你想用信号量也是可以的。
qq120848369 2012-05-10
  • 打赏
  • 举报
回复
1,不会,早晚会读,只要你仔细检查每一个函数的返回值,肯定会检测出来fd失效。
2,不可以,因为信号量只表示有资源可取,但是并不提供同步功能,有10个connection,结果10个worker同时操作队列,所以你应该懂得。另外一个局限性是原本可以借助条件变量+quit全局变量来方便的cond_brocast令所有worker退出,这在进程支持热重启或者在master-worker模型中试图平稳的杀死的worker进程都是很好的办法,因为不会中断正在被服务的connection,而且不需要额外的开发。
verylcg 2012-05-10
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

...

编码完全错误,等着悲剧吧。

正确做法:main线程负责进程与线程管理,listen线程负责监听,worker线程负责I/O。

你这是memcache的网络架构,需要为每个worker线程准备一个pipe和一个connection队列。

listen线程只负责accept,之后RR轮询将accept的conenction分发到其中一个worker,方法为:将cone……
[/Quote]

请问

第一种方式
如果worker的队列没有及时读取,并且此时对方关闭链接,本地还没有close,会不会导致这个socket fd 不能释放

第二种方式
用sem_wait,sem_post 代替条件变量,worker线程池抢夺socket fd 会有问题么

qq120848369 2012-05-10
  • 打赏
  • 举报
回复
...

编码完全错误,等着悲剧吧。

正确做法:main线程负责进程与线程管理,listen线程负责监听,worker线程负责I/O。

你这是memcache的网络架构,需要为每个worker线程准备一个pipe和一个connection队列。

listen线程只负责accept,之后RR轮询将accept的conenction分发到其中一个worker,方法为:将conenction加入该worker的队列,并向该worker线程的pipe写1字节。

而每一个worker线程都应该创建自己的epoll_fd,并且在线程启动后立即将pipe[0]加入监听,如果pipe可读,则读1字节,并从队列中取出一个connection加入epoll监听。

这样由listen线程负责监听与连接的分发,worker线程负责I/O,main负责多线程多进程的动态管理与用户信号管理。

看你说是短连接,发送大量数据的情况:短连接适合这种工作模型,如果处理逻辑是CPU计算而不是磁盘I/O,那么worker线程的工作模式要改变,每个worker只能负责一个connection,listen线程的通知方式也改变,直接采取条件变量+互斥量的全局异步队列,由worker线程池抢夺。如果是读磁盘发数据的话,那问题就简单多了,还是采取每个worker监听N个connection的方案,读磁盘和发数据是可以异步的,即注册connection的write事件,每次回调就可以从磁盘读一些发出去,直到发完为止。

verylcg 2012-05-10
  • 打赏
  • 举报
回复
补充:客户端都是短链接,并且需要发送大量数据给客户端,所以处理的有点延迟.

23,125

社区成员

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

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