并发服务器

背景

在总结socket编程时,如果不考虑到并发问题,服务器与客户端的交互逻辑应该是:

  1. 服务器侦听本地端口上的连接请求(listen);
  2. 客户端向正在被侦听的服务器端口发起连接请求(connect);
  3. 服务器接收到客户端的连接请求,并自动将其加入到连接队列;
  4. 服务器从连接队列取出第一个连接并建立新连接,返回服务端socket套接字;
  5. 服务器尝试从套接字读取数据(recv),这里会阻塞(不设置非阻塞)直到客户端发送数据过来;
  6. 服务器取到数据,尝试向客户端回写数据(阻塞)
  7. 继续读-写循环,也就是进行通信

这种最简单的服务器逻辑,有一个名称:迭代服务器

特点:只与一个客户端进行通信,数据收发操作是有逻辑先后的。

 

多进程服务器:

  • 逻辑:新连接建立后,由主进程为其创建出一个对应的服务进程来处理与客户端的交互,交互完成后子进程退出,并由主进程回收;
  • 需要考虑:最大文件描述符个数,进程个数上限,进程调度对整体性能影响,进程数据共享

多线程服务器:

  • 需要考虑:进程内最大文件描述符个数,线程同步,线程退出处理

多路IO

综合考虑迭代服务器,多进程多线程服务器的缺点,问题的根源在于:

  • 进程或线程对系统资源的过度消耗;
  • 进程与进程,线程与线程之间的协调问题等

多路IO从根源上解决了上面的这些问题,其主旨思想是:

  • 不再由服务器主动判断相关网络事件(新连接,可读,可写等)是否就绪,这避免了阻塞问题;
  • 通过内核转发这些网络事件的就绪状态(事件通知)

三种主要方法:

  • select
  • poll
  • epoll

select,底层基于绑定了多个文件描述符的数组,采用轮询机制(O(n)的轮询复杂度),受限于单个进程可打开的最大文件描述符个数(FD_SETSIZE=1024)

pll,底层基于链表(无监听上限),其他与select基本一致

epoll,内核分别维护一颗红黑树和双向链表,红黑树保存注册的文件描述符,链表保存就绪事件,从内核将就绪链表拷贝到用户态,再对就绪链表进行遍历

 

参考

epoll:

  https://www.jianshu.com/p/beb6980cbb49

  https://blog.csdn.net/zhaobryant/article/details/80557262

  https://blog.csdn.net/shenya1314/article/details/73691088

  

posted on 2020-01-02 11:32  sermatec江  阅读(171)  评论(0编辑  收藏  举报