常规的epoll处理

epoll是io多路复用的一种实现方式,最开始我们使用epoll是对多个fd进行管理,当epoll_wait从内核的rdllist就绪链表中取出一定数量的poll_event时,我们可以根据fd进行相应的处理,比如是listenfd的话,就进行accept操作,再将返回的clientfd通过epoll_ctl加入到内核的红黑树中进行EPOLLIN的监听,如果不是listenfd,说明是clientfd需要被处理,再判断是EPOLLIN还是EPOLLOUT,分别做recv和send的处理,可以看出在这个过程中,需要对fd做出处理,判断是否是listenfd,因为是listenfd的话说明是有新的连接进来,需要做连接接入处理,而是其他fd的话,就要判断是哪种事件了。

当然也可以这样实现,epoll_wait返回后,首先对事件进行判断,看是EPOLLIN还是EPOLLOUT,如果是EPOLLIN的话,还要判断是不是listenfd,因为listenfd也是EPOLLIN事件,不是的话就说明是有传输数据进来,需要recv处理,而对EPOLLOUT事件,说明发送缓冲区可以发送数据了,进行send即可。这种实现方式还是需要对fd进行判断,有没有更优雅的使用方法呢?

epoll事件模型的底层原理

这就是这篇文章要说到的reactor反应堆模型了,它是一种对事件进行管理的模式,先来看看是怎么实现的,epoll_event是我们提供epoll_ctl需要传递给内核的结构体数据,它有一个uint32_t 的events和epoll_data类型的data,epoll_data是一个union联合体,它有一个fd整形和void *ptr指针,重点关注这两个,也就是说,我们可以通过epoll_event传递给内核fd或者是ptr,这些传递进去的fd或者ptr只是为了和events绑定在一起,后面通过epoll_wait取的数据也是epoll_event数据,也就可以知道是哪个fd触发了事件,或者哪个ptr触发了事件,上文提到的就是通过判断是哪个fd触发了事件,那我们这里就是要通过判断是哪个ptr,这个ptr我们可以设置成一个sockitem结构体的地址,这个结构体里面包括了fd和回调函数,在epoll_ctl的时候就将ptr绑定好传递给内核,epoll_wait返回后,直接取出ptr对应的sockitem里面的回调函数执行就行了,比如listenfd的回调函数是accept_cb,clientfd的回调函数有send_cb和recv_cb,epoll_wait后我们可以通过事件来进行区分,EPOLLIN就调用epoll_event对应的ptr里面的回调函数就行,EPOLLOUT也是一样,这些ptr都是epoll_ctl时就绑定好了的,这样我们就将epoll的处理逻辑和业务代码单独处理了,因为回调函数都是处理一些业务的逻辑,也无需判断是不是listenfd,这种自动触发对应的事件处理函数的方法就是反应堆模型。

epoll处理连续数据

对于EPOLLOUT里面的send是需要发送大文件的情况,这种情况一次send是发送不完的,因为发送缓冲区不够大,需要分多次发送,但我们怎么知道上一次是发送到哪个位置了,比如30MB的文件,上次发送了2MB,这次要接着上次2MB的位置继续发送,所以这个2MB的位置信息send_length需要在上次发送完成后保存下来,我们也把它保存着sockitem这个结构体里面,因为sockitem对应的地址也就是上面说的ptr我们是传给内核了的,有事件到来时,内核还会把这个ptr给到应用层,我们就可以从ptr对应的sockitem里取出上次的send_length位置继续发送了,另外我们将需要发送的数据放在sockitem里面的send_buffer里面,一般是在recv_cb里面赋值,比如echo服务器直接将收到的数据recv_buff拷到send_buffer里,send_cb只要这个send_buffer有值就进行send即可。

状态机

对于http服务或者websocket服务,需要在recv_cb里面对接收到的数据进行相对应的协议解析,比如websocket通信前先要进行握手,也就是进行一些鉴权验证,验证通过后才能进行相应的数据传输,针对这个流程可以使用状态机来实现,所以sockitem里面还需要加入一个status字段,recv收到数据根据状态进行处理。

多线程accept

一些对网络接入速度有要求的服务器,我们可以将accept单独交个一个poll进行处理,因为fd就一个,用poll就行,也可以使用多线程管理多个poll,而clientfd则交给epoll进行处理,其具体的事件处理交给线程池去完成,这样就将网络接入和业务处理分离开了,能够快速的响应接入,特别是对于那种重启后突然有大量用户接入的情况有很好的效果。

百万并发

一般情况下,使用epoll做服务器,基本不需要怎么处理都可以达到百万的并发量,这里的并发指的是服务器同一时间能够承载的服务量,一般与内存,数据库,日志和网络带宽等因素有关,并发压测服务器的时候,可以使用多台机器做客户端进行请求,服务器开多个端口进行监听,这样客户端可以启用更多的连接,比较五元组的组合就变得更多一些,还可能需要设置一些参数,如ulimit -n设置最大可打开的文件数,或者修改/etc/security/limits.conf里面的nofile,这个可以永久修改。file-max表示文件描述符的最大值,一般设置的比open files要大。另外tcp的sendbuf和recvbuf可以设置的小一点,这样并发量上来后占用的内存要小一些。当客户端的连接到一定数量的时候,可能会出现连接超时的现象,这可能是内核的一个参数需要修改,nf_conntrack_max,发出去的包被服务器的netfilter给拒绝了。

  • 本文作者: nephen
  • 本文链接: epoll服务器反应堆模型 | Nephen's Blog
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!

epoll服务器反应堆模型相关推荐

  1. epoll反应堆模型

    ================================ 下面代码实现的思想:epoll反应堆模型:( libevent 网络编程开源库 核心思想) 1. 普通多路IO转接服务器: 红黑树 ― ...

  2. Epoll 反应堆模型核心原理及代码讲解

    Epoll 反应堆模型核心原理及代码讲解 [Ⅰ] Epoll 原理及应用 && ET模式与LT模式 [Ⅱ] Epoll 反应堆模型核心原理及代码讲解 一.反应堆核心原理 二.反应堆模型 ...

  3. Linux网络编程7——epoll反应堆模型

    学习视频链接 16-epoll反应堆main逻辑_bilibili_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1iJ411S7UA?p=81& ...

  4. linux网络编程 epoll水平触发、边沿触发、反应堆模型、线程池思想

    打开文件上限的设置可修改配置文件: etc/security/limits.conf 水平.边沿触发: 若客户端发送1000B数据,服务器一次只读500B.在水平触发的模式下,服务器会再调用一次epo ...

  5. 基础服务器 IO 模型 Proactor 模型 Reactor 模型 IO 多路复用 异步 IO 模型 Linux 服务器开发 网络编程服务器模型

    本文主要记录服务器的 IO 模型的类型(从多路复用,异步 IO 讲到 Proactor Reactor 模型),包括 Real World nginx 和 apache ,kafka 等分析,配备自洽 ...

  6. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较

    在<朴素.Select.Poll和Epoll网络编程模型实现和分析--模型比较>一文中,我们分析了各种模型在处理短连接时的能力.本文我们将讨论处理长连接时各个模型的性能.(转载请指明出于b ...

  7. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Epoll模型

    在阅读完<朴素.Select.Poll和Epoll网络编程模型实现和分析--Select模型>和<朴素.Select.Poll和Epoll网络编程模型实现和分析--Poll模型> ...

  8. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll模型

    在<朴素.Select.Poll和Epoll网络编程模型实现和分析--Select模型>中,我们分析了它只能支持1024个连接同时处理的原因.但是在有些需要同时处理更多连接的情况下,102 ...

  9. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Select模型

    在<朴素.Select.Poll和Epoll网络编程模型实现和分析--朴素模型>中我们分析了朴素模型的一个缺陷--一次只能处理一个连接.本文介绍的Select模型则可以解决这个问题.(转载 ...

最新文章

  1. IE6左右边框断线现象
  2. windows phone (23) ScrollViewer元素
  3. MySQL-MongoDB开源监控利器之PMM
  4. 关于mbzuai的offer的三点思考
  5. Swift之缓存文件处理
  6. PL SQL导入导出sql/dmp文件
  7. 信息学奥赛一本通C++语言——1120:同行列对角线的格
  8. 查看linux内存优化,Linux性能优化和监控系列(三) 分析Memory使用状况
  9. 董明珠:雷军的产品基本是贴牌生产,若自己建厂,他肯定做不过我
  10. 探究position定位中absolute和relative的异同
  11. Gpower软件真不错
  12. html5妇女节游戏,html5开发三八女王节表白神器
  13. 使用Bandwagon服务器ftp解决git clone速度慢的问题
  14. 英语六级试卷软件测试,背单词软件_2018年12月英语六级考试真题测试(11)含答案_沪江英语...
  15. 拓嘉辰丰:怎样把买家秀做好促进转化
  16. 惠普HP Deskjet 1010 打印机驱动
  17. 【Unity3D游戏开发学习笔记】(六)上帝之手—GameObject的操作
  18. Linux命令yun安装nginx并使用
  19. IEC 61131标准系列
  20. 【redis源码学习】redis 中的“消息队列” Stream

热门文章

  1. 编译原理学习笔记(十九)~习题:将语句翻译为三地址代码
  2. 如何在Adobe Reader中存储阅读的Session
  3. react 使用 useEffect 及踩坑
  4. 大专生出身?java技术栈xmind
  5. 你的人生你定义!享你所想,无惧冒险
  6. stata学习笔记|OLS回归
  7. ad10搜索快捷键_AD10设计所需快捷键(席雪晴)
  8. 计算机视觉——计算视差图
  9. 【JAVA今法修真】 第五章 练气百日,筑基三年
  10. windows7、ubuntu双系统安装