Nginx源码研究三:Epoll在NGINX中的使用
Web服务器在面对高并发的情况下,网络的IO一般选择IO复用,像apache选择的Select/poll。Nginx在linux 2.6后选择Epoll做网路IO,提高了WEB服务的并发能力。
在本章,我们将看看NGINX如何使用epoll。
首先,我们看一下数据结构图:
1、从结构图中,我们先看第一部分,NGINX拿到socket标示符,绑定本地地址,监听socket标示符信息,由于NGINX支持多server,支持各个server使用不同的端口、不同的协议族。如此需要多个socket句柄来支持,NGINX利用ngx_listening_t这个数据结构来保存打开的socket信息并且放置在一个数组里面。这个过程是在初始化cycle中完成的。
2、关于socket句柄,我们区分两类,一类是上一部分说的服务端申请的socket,这一部分socket处理和客户端连接的情况,如果有新的连接进来,将会产生关于这一批socket的事件;第二类,是连接建立后,服务端accept客户端的socket句柄,针对这个句柄,服务端做读和写的操作。
我们再看一下下图绘制的一个处理流程。
我们再通过代码来看看整个过程
分析配置文件,申请socket fd
2、处理事件模块的初始化
static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) {.......//对所有NGX_EVENT_MODULE模块执行module->actions.initfor (m = 0; ngx_modules[m]; m++) {if (ngx_modules[m]->type != NGX_EVENT_MODULE) {continue;}if (ngx_modules[m]->ctx_index != ecf->use) {continue;}module = ngx_modules[m]->ctx;if (module->actions.init(cycle, ngx_timer_resolution) != NGX_OK) {/* fatal */exit(2);}break;}......cycle->connections =ngx_alloc(sizeof(ngx_connection_t) * cycle->connection_n, cycle->log);if (cycle->connections == NULL) {return NGX_ERROR;}c = cycle->connections;cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,cycle->log);if (cycle->read_events == NULL) {return NGX_ERROR;}rev = cycle->read_events;for (i = 0; i < cycle->connection_n; i++) {rev[i].closed = 1;rev[i].instance = 1; #if (NGX_THREADS)rev[i].lock = &c[i].lock;rev[i].own_lock = &c[i].lock; #endif}cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * cycle->connection_n,cycle->log);if (cycle->write_events == NULL) {return NGX_ERROR;}wev = cycle->write_events;for (i = 0; i < cycle->connection_n; i++) {wev[i].closed = 1; #if (NGX_THREADS)wev[i].lock = &c[i].lock;wev[i].own_lock = &c[i].lock; #endif}i = cycle->connection_n;next = NULL;do {i--;c[i].data = next;c[i].read = &cycle->read_events[i];c[i].write = &cycle->write_events[i];c[i].fd = (ngx_socket_t) -1;next = &c[i];#if (NGX_THREADS)c[i].lock = 0; #endif} while (i);cycle->free_connections = next;cycle->free_connection_n = cycle->connection_n;/* for each listening socket */ls = cycle->listening.elts;for (i = 0; i < cycle->listening.nelts; i++) {//获取空余连接,将服务端申请的每个socket fd占用一个连接,c = ngx_get_connection(ls[i].fd, cycle->log);......rev->handler = ngx_event_accept;if (ngx_use_accept_mutex) {continue;}if (ngx_event_flags & NGX_USE_RTSIG_EVENT) {if (ngx_add_conn(c) == NGX_ERROR) {return NGX_ERROR;}} else {//如果使用epoll模块,则在epoll上注册读事件,操作类型是EPOLL_CTL_ADD,也就是关注服务端申请的socket fd是否有新连接申请if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) {return NGX_ERROR;}}}return NGX_OK; }
3、 EPOLL在发现新事件后,会查找处理该事件的方法,实际上先查找对应的连接,该连接指针是如下方式,利用epoll_event结构体成员data的ptr指针可以用来存储用户的连接信息,我们在看看后面是怎么处理的
static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) {.......//epoll_event结构体成员data的ptr指针可以用来存储用户的指针信息,这里用来存储连接信息,其中事件的instance标识主要用来显示事件是否过期 ee.events = events | (uint32_t) flags;ee.data.ptr = (void *) ((uintptr_t) c | ev->instance); //把instance加到ee的末尾(由于内存对齐,末尾一般为0) …….if (epoll_ctl(ep, op, c->fd, &ee) == -1) {ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,"epoll_ctl(%d, %d) failed", op, c->fd);return NGX_ERROR;}.......return NGX_OK; }
4、
static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data) {......ngx_worker_process_init(cycle, worker);......for ( ;; ) {......ngx_process_events_and_timers(cycle);......} }
5、
void ngx_process_events_and_timers(ngx_cycle_t *cycle) {......(void) ngx_process_events(cycle, timer, flags);......}
转载于:https://www.cnblogs.com/yimuren/p/4105124.html
Nginx源码研究三:Epoll在NGINX中的使用相关推荐
- Nginx源码研究之nginx限流模块详解
这篇文章主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 高并发系统有三把利器:缓存.降级和限流: 限流的目的是通过对并 ...
- Nginx源码分析:epoll事件处理模块概述
nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...
- distcc源码研究三
作者:朱金灿 来源:http://blog.csdn.net/clever101 继续研究distcc.今天我在思考这样一个问题:分布式编译系统本身并不是编译器,它本质是一个编译请求的发起者和执行者, ...
- nginx源码分析—内存池结构ngx_pool_t及内存管理
本博客( http://blog.csdn.net/livelylittlefish)贴出作者(阿波)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.内存池结构 1.1 ...
- Nginx 源码分析
1.工程 ngx_conf_file.c ngx_connection.c ngx_cycle.c ngx_file.h ngx_module.c ngx_open_file_cache.h ngx_ ...
- 阿里中间件seata源码剖析六:TCC模式中2阶段提交实现
目录 TM通知TC事务状态 TC通知RM分支事务提交 RM处理TC提交事务请求 总结 上篇文章中,我们以TCC模式的demo为例,讲解了seata中全局事务的开启.在这个demo中,TM作为一个全局事 ...
- 设计模式在C语言中的应用--读nginx源码
市面上的"设计模式"书籍文章,皆针对Java/C++/C#等面向对象语言,似乎离开了面向对象的种种特性,设计模式就无法实现,没有用武之地了. 是这样吗?设计模式的概念是从建筑领域引 ...
- 如何高效的学习 Nginx 源码,汲取养分?
Nginx 的功能点比较多,涉及到的新概念和设计思路对于新手也不是特别友好,我建议在了解一些了 Nginx 的一些基础知识之后,通过调试来学习 Nginx 源码. 以下操作需要一些 gdb 调试知识, ...
- Nginx源码安装及调优配置
由于Nginx本身的一些优点,轻量,开源,易用,越来越多的公司使用nginx作为自己公司的web应用服务器,本文详细介绍nginx源码安装的同时并对nginx进行优化配置. Nginx编译前的优化 [ ...
最新文章
- 规格表管理之更新规格表数据
- iOS快速上手应用内购(IAP)附Demo
- ubuntu 源更新(sources.list)
- UIButton 按钮控件-IOS开发 (实例)
- 脑动力:C语言函数速查效率手册(附DVD光盘1张) [平
- vue keep-alive保存路由状态2 (高级用法,接上篇)
- [公告]博客园恢复正常运行
- 划分VLAN,以及VLAN间通信
- 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十二║Vue实战:个人博客第一版(axios+router)...
- 今天拿到了同事给我买的《java与模式》
- python生成器yield原理_Python generator生成器和yield表达式详解
- 智能仓储管理系统分析?
- python虚拟cpu性能_基于Tensorflow:CPU性能分析
- python能做什么程序-Python可以被用来做哪些神奇好玩的事情
- BeanFactory not initialized or already closed - call 'refresh' before access
- 利用条件随机场模型进行中文分词
- python培训机构 马哥
- java中feli删除操作_Feli的生日礼物
- 全国计算机考试一级理论,全国计算机等级考试一级理论汇总(版).docx
- 解决变频器干扰低压电子设备的经验
热门文章
- 免费的网络推广教大家新站点前期优化如何进行?
- 我的世界java存档怎么导入_我的世界:地图种子输入“skull”,真的会找到沙漠骷髅岛么?...
- opengl 深度详解_一步步学OpenGL(1) -《打开一个窗口》
- android log4,GitHub - oronno/log4android: Log4Android - Simple Logging Wrapper Library for Android
- 天龙固件U盘更新_硅格T18D量产工具下载_硅格T18D量产工具官方版下载[u盘格式化]...
- wireshark 抓包再利用TCP socket发送包里的payload是可以实现登陆的
- mysql 权重搜索
- JD AWS vue上传文件
- JD boto3 flask 上传 demo
- [题解]洛谷P1119 灾后重建