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中的使用相关推荐

  1. Nginx源码研究之nginx限流模块详解

    这篇文章主要介绍了Nginx源码研究之nginx限流模块详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考.一起跟随小编过来看看吧 高并发系统有三把利器:缓存.降级和限流: 限流的目的是通过对并 ...

  2. Nginx源码分析:epoll事件处理模块概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 事件处理模块概述 Nginx的高效请求的处理依赖于事件管理机制,本次默认的场景是Linux操 ...

  3. distcc源码研究三

    作者:朱金灿 来源:http://blog.csdn.net/clever101 继续研究distcc.今天我在思考这样一个问题:分布式编译系统本身并不是编译器,它本质是一个编译请求的发起者和执行者, ...

  4. nginx源码分析—内存池结构ngx_pool_t及内存管理

    本博客( http://blog.csdn.net/livelylittlefish)贴出作者(阿波)相关研究.学习内容所做的笔记,欢迎广大朋友指正! Content 0.序 1.内存池结构 1.1 ...

  5. Nginx 源码分析

    1.工程 ngx_conf_file.c ngx_connection.c ngx_cycle.c ngx_file.h ngx_module.c ngx_open_file_cache.h ngx_ ...

  6. 阿里中间件seata源码剖析六:TCC模式中2阶段提交实现

    目录 TM通知TC事务状态 TC通知RM分支事务提交 RM处理TC提交事务请求 总结 上篇文章中,我们以TCC模式的demo为例,讲解了seata中全局事务的开启.在这个demo中,TM作为一个全局事 ...

  7. 设计模式在C语言中的应用--读nginx源码

    市面上的"设计模式"书籍文章,皆针对Java/C++/C#等面向对象语言,似乎离开了面向对象的种种特性,设计模式就无法实现,没有用武之地了. 是这样吗?设计模式的概念是从建筑领域引 ...

  8. 如何高效的学习 Nginx 源码,汲取养分?

    Nginx 的功能点比较多,涉及到的新概念和设计思路对于新手也不是特别友好,我建议在了解一些了 Nginx 的一些基础知识之后,通过调试来学习 Nginx 源码. 以下操作需要一些 gdb 调试知识, ...

  9. Nginx源码安装及调优配置

    由于Nginx本身的一些优点,轻量,开源,易用,越来越多的公司使用nginx作为自己公司的web应用服务器,本文详细介绍nginx源码安装的同时并对nginx进行优化配置. Nginx编译前的优化 [ ...

最新文章

  1. 规格表管理之更新规格表数据
  2. iOS快速上手应用内购(IAP)附Demo
  3. ubuntu 源更新(sources.list)
  4. UIButton 按钮控件-IOS开发 (实例)
  5. 脑动力:C语言函数速查效率手册(附DVD光盘1张) [平
  6. vue keep-alive保存路由状态2 (高级用法,接上篇)
  7. [公告]博客园恢复正常运行
  8. 划分VLAN,以及VLAN间通信
  9. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十二║Vue实战:个人博客第一版(axios+router)...
  10. 今天拿到了同事给我买的《java与模式》
  11. python生成器yield原理_Python generator生成器和yield表达式详解
  12. 智能仓储管理系统分析?
  13. python虚拟cpu性能_基于Tensorflow:CPU性能分析
  14. python能做什么程序-Python可以被用来做哪些神奇好玩的事情
  15. BeanFactory not initialized or already closed - call 'refresh' before access
  16. 利用条件随机场模型进行中文分词
  17. python培训机构 马哥
  18. java中feli删除操作_Feli的生日礼物
  19. 全国计算机考试一级理论,全国计算机等级考试一级理论汇总(版).docx
  20. 解决变频器干扰低压电子设备的经验

热门文章

  1. 免费的网络推广教大家新站点前期优化如何进行?
  2. 我的世界java存档怎么导入_我的世界:地图种子输入“skull”,真的会找到沙漠骷髅岛么?...
  3. opengl 深度详解_一步步学OpenGL(1) -《打开一个窗口》
  4. android log4,GitHub - oronno/log4android: Log4Android - Simple Logging Wrapper Library for Android
  5. 天龙固件U盘更新_硅格T18D量产工具下载_硅格T18D量产工具官方版下载[u盘格式化]...
  6. wireshark 抓包再利用TCP socket发送包里的payload是可以实现登陆的
  7. mysql 权重搜索
  8. JD AWS vue上传文件
  9. JD boto3 flask 上传 demo
  10. [题解]洛谷P1119 灾后重建