nginx学习之epoll

nginx 多进程进程 epoll 问题:          有一个单进程的linux epoll服务器程序,近来希望将它改写成多进程版本,          主要原因有:                 1、在服务高峰期间 并发的 网络请求非常大,目前的单进程版本的支撑不了:单进程时只有一个循环先后处理epoll_wait()到的事件,使得某些不幸排队靠后的socket fd的网络事件得不到及时处理;           阅读详情

首先说一下传统的I/O多路复用select和poll,对比一下和epoll之间的区别:

举个例子:假如有100万用户同时与一个进程保持TCP连接,而每一时刻只有几十或者几百个tcp连接是活跃的(即能接收到TCP包),那么在每一时刻进程只需要处理这100万连接中的一小部分。

select和poll这样处理的:在某一时刻,进程收集所有的连接,其实这100万连接中大部分是没有时间发生的。因此,如果每次收集事件时,都把这100万连接的套接字传给操作系统(这首先就是用户态内存到内核内存的大量复制),而由操作系统内核寻找这些链接上没有处理的事件,将会是巨大的浪费。

而epoll是这样做的:epoll把select和poll分为了两个部分,

1、调用epoll_creat建立一个epoll对象。

2、调用epoll_ctl向epoll对象中添加这100万个连接的套接字。

3、调用epoll_wait收集发生事件的连接。=》重点是在这里,调用epoll_wait收集所有发生的事件的连接,并将事件放在一个链表中,这样只需到该链表中寻找发生连接的事件,而不用遍历100万连接!这样在实际收集事件时,epoll_wait效率会很高。


三个系统调用函数都是用C进行封装,在《深入理解Nginx》P310中由函数详细说明,下面简单介绍一下。

  1. int epoll_create(int size);    
  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);    
  3. int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);  
首先要调用epoll_create建立一个epoll对象。参数size是内核保证能够正确处理的最大句柄数,多于这个最大数时内核可不保证效果。

epoll_ctl可以操作上面建立的epoll,例如,将刚建立的socket加入到epoll中让其监控,或者把 epoll正在监控的某个socket句柄移出epoll,不再监控它等等。

epoll_wait在调用时,在给定的timeout时间内,当在监控的所有句柄中有事件发生时,就返回用户态的进程。


那么epoll是如何实现以上想法的呢?

当某一个进程调用epoll_creat方法时,linux内核会创建一个eventpoll结构体,这个结构体中有两个成员的使用与epoll的使用方式密切相关。

  1. struct eventpoll {  
  2.     //红黑树的根节点,这棵树中存储着所有添加到epoll中的事件,也就是这个epoll监控的事件。  
  3.     struct rb_root rbr;  
  4.     //双向链表rdllist保存着将要通过epoll_wait返回给用户的、满足条件的事件。  
  5.     struct list_head rdllist;  
  6. }  

epoll为何如此高效:

当我们调用epoll_ctl往里塞入百万个句柄时,epoll_wait仍然可以飞快的返回,并有效的将发生事件的句柄给我们用户。这是由于我们在调用epoll_create时,内核除了帮我们在epoll文件系统里建了个file结点,在内核cache里建了个红黑树用于存储以后epoll_ctl传来的socket外,还会再建立一个list链表,用于存储准备就绪的事件,当epoll_wait调用时,仅仅观察这个list链表里有没有数据即可。有数据就返回,没有数据就sleep,等到timeout时间到后即使链表没数据也返回。所以,epoll_wait非常高效。


而且,通常情况下即使我们要监控百万计的句柄,大多一次也只返回很少量的准备就绪句柄而已,所以,epoll_wait仅需要从内核态copy少量的句柄到用户态而已,如何能不高效?!


那么,这个准备就绪list链表是怎么维护的呢?当我们执行epoll_ctl时,除了把socket放到epoll文件系统里file对象对应的红黑树上之外,还会给内核中断处理程序注册一个回调函数,告诉内核,如果这个句柄的中断到了,就把它放到准备就绪list链表里。所以,当一个socket上有数据到了,内核在把网卡上的数据copy到内核中后就来把socket插入到准备就绪链表里了。


如此,一颗红黑树,一张准备就绪句柄链表,少量的内核cache,就帮我们解决了大并发下的socket处理问题。执行epoll_create时,创建了红黑树和就绪链表,执行epoll_ctl时,如果增加socket句柄,则检查在红黑树中是否存在,存在立即返回,不存在则添加到树干上,然后向内核注册回调函数,用于当中断事件来临时向准备就绪链表中插入数据。执行epoll_wait时立刻返回准备就绪链表里的数据即可。


最后看看epoll独有的两种模式LT和ET。无论是LT和ET模式,都适用于以上所说的流程。区别是,LT模式下,只要一个句柄上的事件一次没有处理完,会在以后调用epoll_wait时次次返回这个句柄,而ET模式仅在第一次返回。


这件事怎么做到的呢?当一个socket句柄上有事件时,内核会把该句柄插入上面所说的准备就绪list链表,这时我们调用epoll_wait,会把准备就绪的socket拷贝到用户态内存,然后清空准备就绪list链表,最后,epoll_wait干了件事,就是检查这些socket,如果不是ET模式(就是LT模式的句柄了),并且这些socket上确实有未处理的事件时,又把该句柄放回到刚刚清空的准备就绪链表了。所以,非ET的句柄,只要它上面还有事件,epoll_wait每次都会返回。而ET模式的句柄,除非有新中断到,即使socket上的事件没有处理完,也是不会次次从epoll_wait返回的。


epoll的优点:

1.支持一个进程打开大数目的socket描述符(FD)

    select 最不能忍受的是一个进程所打开的FD是有一定限制的,由FD_SETSIZE设置,默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显然太少了。这时候你一是可以选择修改这个宏然后重新编译内核,不过资料也同时指出这样会带来网络效率的下降,二是可以选择多进程的解决方案(传统的 Apache方案),不过虽然linux上面创建进程的代价比较小,但仍旧是不可忽视的,加上进程间数据同步远比不上线程间同步的高效,所以也不是一种完美的方案。不过 epoll则没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左右,具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。

 

2.IO效率不随FD数目增加而线性下降

    传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合,不过由于网络延时,任一时间只有部分的socket是"活跃"的,但是select/poll每次调用都会线性扫描全部的集合,导致效率呈现线性下降。但是epoll不存在这个问题,它只会对"活跃"的socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么,只有"活跃"的socket才会主动的去调用 callback函数,其他idle状态socket则不会,在这点上,epoll实现了一个"伪"AIO,因为这时候推动力在os内核。在一些 benchmark中,如果所有的socket基本上都是活跃的---比如一个高速LAN环境,epoll并不比select/poll有什么效率,相反,如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle connections模拟WAN环境,epoll的效率就远在select/poll之上了。

 

3.使用mmap加速内核与用户空间的消息传递

    这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间,如何避免不必要的内存拷贝就很重要,在这点上,epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话,一定不会忘记手工 mmap这一步的。

 

4.内核微调

这一点其实不算epoll的优点了,而是整个linux平台的优点。也许你可以怀疑linux平台,但是你无法回避linux平台赋予你微调内核的能力。比如,内核TCP/IP协议栈使用内存池管理sk_buff结构,那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大小--- 通过echo XXXX>/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手的数据包队列长度),也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网卡驱动架构。

jsp利用smartLoad实现上传下载 1.在填写表单时需要进行日期、数字等校验,这可以用jQuery easyUI来实现,非常方便。 使用jquery easyui时需导入类似jquery-easyui-1.3.1的包,然后在jsp页面引入相应的文件,一般来说是4个。 2.上传时需注意两点,method="post"和enctype="multipart/form-data". 3.BaseDao是一个 阅读详情

相关推荐

VirtualBox下安装solaris 10

医院的放疗计划系统Pinnacle安装在solaris 10系统之上,为了方便学习,我在自己的老本thinkpad E420上构建学习环境。 首先,笔记本是win7旗舰版,考虑到经常调试网络,直接安装了华为的eNSP,这个软件封装着VirtualBox,几经反复终于安装成功,现在把过程记录于朋友们分享,希望大家在学习中多交流。 一、下载 因为eNSP版本更新以及华为官网页面的变化,有的朋友安...

qiupi的专栏 814

nginx死循环解决办法

问题描述 前后端分别部署在不同的服务器中,它们的访问域名不一致,前端访问域名是front.my.com,后端访问域名是server.my.com。为了解决跨域问题,前端调用后端接口通过nginx反向代理实现。 nginx配置 server{ listen 80; server front.my.com; proxy_set_header Host $host; pro...

yihanzhi的博客 5950

04 Weblogic之受管服务器 配置受管服务器,启动受管服务器,解决因为强制关闭Weblogic之后导致启动有问题的

04 Weblogic之受管服务器 配置受管服务器,启动受管服务器,解决因为强制关闭Weblogic之后导致启动有问题的

qq_44884269的博客 1229

【Nginx 学习之路】高并发之epoll模型详解

epoll是一种高效的事件驱动I/O模型,它是Linux内核提供的一种I/O多路复用机制,可以同时监控多个文件描述符的I/O事件,当有文件描述符就绪时,可以立即通知用户态程序进行处理,从而提高了I/O操作的效率和并发处理能力。epoll的核心思想就是利用内核的事件通知机制,将连接套接字加入到一个事件表中,当连接套接字上有I/O事件发生时,内核会通过事件通知机制通知应用程序进行处理。

Stephen_Daa的博客 1754

JavaEE复习笔记(2)——JSP

1、JSP页面由两部分构成: ·静态部分:标准的HTML标签、静态的页面内容。这些内容与静态的HTML 页面相同。 ·动态部分:受Java程序控制的内容,这些内容由Java程序来动态生成 2、JSP页面中 和 %>之间放置Java脚本。 3、JSP生成的servlet文件放在work路径对应的web目录下。 4、相关说明: ·JSP文件在JSP服务器内运行。 ·JSP文件必须生成

<code> I am a coder </code> 1106

Jsp下调用ocx组件

1.ocx插件的注册 地址参考:http://www.360doc.com/content/14/0806/15/14264700_399857788.shtml 注册比较简单主要参考上面的地址就可以; 2.了解中各参数的含义 /XXX.OCX#version=65536"> 1.ID:为控件提供一个标识名称,为HTML代码提供一种访问该控件的入口。 2.CLASS

Tiger的专栏 1196

nginx epoll详解

nginx epoll 事件模型     nginx做为一个异步高效的事件驱动型web服务器,在linux平台中当系统支持epoll时nginx默认采用epoll来高效的处理事件。nginx中使用ngx_event_t结构来表示一个事件,先介绍下ngx_event_t结构体中成员的含义: struct ngx_event_s { void *data;

linux专栏 1万+

IDEA 2023+如何搭建传统JavaWeb项目(Servlet/JSP/WAR)

JavaWeb开发指基于Servlet、JSP和WAR包部署的传统Web应用架构,其核心原理是通过Servlet容器(如Tomcat)解析web.xml或注解,管理请求生命周期与资源映射。技术价值在于底层可控、教学清晰、兼容存量系统,广泛应用于高校课程实验、政务/金融老系统维护及Filter/Listener等容器机制深度调试。典型应用场景包括手写HelloWorldServlet、JSP动态页面渲染、web.xml配置驱动的URL映射,以及对接Tomcat实现热部署调试。本文聚焦IntelliJ IDEA

weixin_29306875的博客 159

Eclipse新版本Web项目配置原理与JSP部署详解

Dynamic Web Project是Java Web开发的基础工程类型,其核心依赖Servlet规范、Tomcat容器和Eclipse的Project Facets机制。随着Eclipse 2020-06起架构升级,项目不再默认生成WebContent物理目录,转而通过Deployment Assembly实现逻辑路径映射,本质是从‘物理目录驱动’向‘逻辑部署驱动’演进。这一变化直接影响web.xml生成策略(由Dynamic Web Module版本决定)、JSP编译行为(依赖Jasper与Eclip

weixin_31102231的博客 269

JSP入门实战:从环境搭建到MVC模式,掌握JavaWeb动态页面核心技术

在JavaWeb开发中,动态页面技术是实现服务器端逻辑与用户界面交互的核心。其基本原理是通过服务器端执行代码,动态生成HTML内容并返回给浏览器,从而实现数据的实时渲染与个性化展示。这项技术的核心价值在于实现了业务逻辑与展示层的初步分离,提升了代码的可维护性和复用性。在众多应用场景中,从传统的企业级应用到需要服务端渲染的内部管理系统,掌握动态页面技术都是后端开发者的必备技能。本文聚焦于JSP(JavaServer Pages)这一经典技术,它作为JavaEE体系中的标准视图组件,是理解后续Spring MV

weixin_33841503的博客 487

IntelliJ IDEA 2024.1 + Tomcat 10 配置 Java Web 开发环境:5步解决 404 与乱码问题

本文详细介绍了如何在IntelliJ IDEA 2024.1中配置Tomcat 10以搭建Java Web开发环境,重点解决常见的404错误和中文乱码问题。通过5个关键步骤,包括环境准备、Tomcat服务器配置、项目结构设置、编码问题解决方案及常见问题排查,帮助开发者快速搭建高效稳定的开发环境。

cnvdkx2837的博客 415

ISE14.7在Win10下安装排障指南:License与JTAG驱动冲突解析

在FPGA开发中,EDA工具链的稳定运行是项目推进的关键。Xilinx ISE 14.7作为支持Spartan-6等老器件的最后版本,至今仍在工业与教学场景中广泛使用。然而,它在Windows 10系统上常因驱动签名策略和License验证机制而出现安装失败、授权失效或JTAG连接中断等问题。从软件授权原理看,License文件绑定主机HOSTID,需通过LM_LICENSE_FILE环境变量正确加载;从驱动兼容性看,老旧USB驱动需在禁用签名强制的环境下手动安装,并注意与ST-Link等调试器的USB端口

weixin_34216196的博客 353

UEditor历史版本安全审计指南:PHP/.NET/JSP各版本文件上传漏洞盘点与修复建议

本文深入分析了UEditor历史版本在PHP/.NET/JSP中的文件上传漏洞、存储型XSS和SSRF等安全隐患,提供了详细的修复建议和加固方案。通过实战案例和代码示例,帮助企业构建全面的防御体系,确保Web应用安全。

weixin_33674976的博客 263

ROS 2 Dashing:从参数声明到QoS强制的工程化演进

ROS 2 是面向机器人系统的分布式通信框架,其核心依赖于DDS中间件与标准化节点交互范式。理解其设计原理,关键在于把握‘声明式编程’与‘显式QoS配置’两大技术基石——前者通过参数声明(declare_parameter)实现编译期契约校验,提升配置可追溯性与IDE支持能力;后者以历史深度(History Depth)等QoS策略的强制设定,保障消息传输的可靠性、实时性与内存可控性。这些机制共同构成现代ROS 2节点的健壮性底座,广泛应用于AGV调度、无人机控制、手术机器人等对稳定性要求严苛的工业场景。本

tomfish 259

JSP在线课堂互动教学系统设计与实现:从表结构到部署排错全指南

在JavaWeb开发中,JSP作为传统动态网页技术,仍是理解HTTP请求、Servlet生命周期与Session状态管理的入门基石。通过分层架构(JSP+Servlet+JavaBean+DAO)与过滤器实现登录鉴权和角色权限控制,能清晰展现Web应用的核心原理。这类系统在高校课程设计与毕业设计中有广泛应用,覆盖用户管理、课程资源、作业提交、互动讨论等关键功能。本文以在线课堂互动教学系统为例,梳理从需求拆解、数据库设计(含用户、课程、作业等核心表)到环境搭建、文件上传及部署排错的完整流程,帮助学习者规避To

weixin_31714129的博客 279

项目开发中常见乱码问题的处理经验总结

Java Web项目乱码问题解决方案 本文针对Java Web项目中常见的乱码问题,从场景分类、排查思路到解决方案进行了系统梳理。文章首先归纳了8种高频乱码场景,涵盖项目初始化、数据库交互、前后端接口等全流程。核心解决思路是"先统一编码,再定位环节",建议将项目全局编码统一为UTF-8,并通过分段验证定位问题根源。针对不同场景提供了具体解决方案,包括IDE编码配置、JSP文件声明、数据库连接参数优化以及前后端接口的POST/GET请求处理等。特别强调了对MySQL数据库使用utf8mb4

热爱音乐和二次元! 1290

Playwright 爬虫:Python 爬取 JS 渲染的 JSP 网站

而 Playwright 基于真实浏览器内核(Chromium、Firefox、WebKit)运行,能完全模拟用户的浏览器行为,让爬虫看到的页面内容与用户完全一致,彻底解决 JS 渲染 JSP 页面的爬取难题。对于开发者而言,掌握 Playwright 爬虫技术,不仅能解决 JSP 网站的爬取难题,更能应对所有前端 JS 渲染的动态网页,全面提升爬虫开发能力。(列表数据通过 JS 异步加载、支持分页、需要等待页面渲染)为例,编写完整的爬虫代码,实现数据爬取、分页处理、数据保存功能。

Z_suger7的博客 1374

FAST_LIO_ROS2 可以用gazebo仿真吗?

摘要:FAST_LIO_ROS2可与Gazebo仿真环境兼容,通过订阅Gazebo模拟的激光雷达和IMU数据实现SLAM建图。已有开源项目(如pb_rm_simulation)验证了该方案,支持导航模式切换与真实机器人移植。关键步骤包括环境配置、传感器话题匹配及参数调试,需注意版本兼容性与数据噪声处理。相关教程提供了从环境搭建到三维建图的完整流程。

专注 激光SLAM, 目标检测, 欢迎关注, 分享交流! 1138
上一篇: Java实现XSS防御
下一篇: Nginx 服务器 select 和epoll的区别
Laputa_Net
博客等级 码龄9年 5粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值