zoukankan      html  css  js  c++  java
  • [转]网络服务器中生产者/消费者模型中的队列问题

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

    多线程模型的网络服务器中,一般有专门的网络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

  • 相关阅读:
    动态获取页面参数内容
    服务器处理静态文件请求
    最简单的Web服务器
    控制台浏览器代码实战
    4.caffe资源汇总(更新中)
    3. caffe中 python Notebook
    2.caffe初解
    1.caffe初入
    有监督学习和无监督学习
    MySQL 之基础操作及增删改查等
  • 原文地址:https://www.cnblogs.com/huazi/p/2604288.html
Copyright © 2011-2022 走看看