[转]网络服务器中生产者/消费者模型中的队列问题

感谢大熊同学为我解惑,这篇帖子的原创权属于大熊。

 

多线程模型的网络服务器中,一般有专门的网络IO线程,将请求放到请求队列中,此为生产者。然后多个工作线程从队列中获取其中一个请求,进行处理,此是消费者。

通常,通讯使用的队列为锁无关队列。且,为了避免CPU耗慢,当工作线程发现队列为空的时候,要睡眠一会儿。

要命的问题就出在这个睡眠上:

1、假设睡眠的时间是10ms,则当队列为空时,所有工作线程都陆续进入睡眠状态;

2、假设工作线程睡眠期间来了请求,则可能队列中的所有请求都会被延迟10ms才能处理到;

3、在整个服务器的运行周期里,队列为空的几率非常大,因此导致工作线程睡眠的几率也非常大。

 

毫无疑问,用以上的方法写服务器,延迟高,且性能上不去。

为什么不一有数据到队列,就有工作线程立即去处理呢?(且CPU不能因为轮询空跑)

传统的方法当然是semaphone, condition variable,大熊同学还提了一种开源代码中广泛采用的方案:

1. 用socketpair()系统调用产生两个fd,一个read_fd,一个write_fd

2. 生产者线程写数据到队列后,往write_fd中写入一个字节

3. 工作线程使用read_fd,然后使用epoll_wait等待read_fd上的事件

4. 当epoll_wait返回的时候,工作线程从队列中就能立即取到请求了

5. 工作线程最后还得从read_fd中读出一个字节

 

以上方案有什么好处呢?

1、队列的检查,不再是基于轮询-睡眠模式,而是基于事件的模式,有数据马上处理,延迟最小;

2、当多个工作线程存在的时候,每个线程都有监听自己的read_fd,所以可以实现按权重等各种复杂的调度算法;

 

缺点也还是有的:

1、每个工作线程创建的时候,都得调用socketpair()

2、每个线程要占用两个文件句柄

 

如果可以,后续希望可以测试一下:轮询-睡眠,socketpair()+epoll_wait(),semaphone,condition variable四种方式的性能的优劣。

http://hi.baidu.com/ah__fu/item/587e86d62f35cccb1b72b46e

转载于:https://www.cnblogs.com/huazi/archive/2012/07/23/2604288.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值