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.init
for (m = ; 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();
} 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 = ; i < cycle->connection_n; i++) {
rev[i].closed = ;
rev[i].instance = ;
#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 = ; i < cycle->connection_n; i++) {
wev[i].closed = ;
#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) -; next = &c[i]; #if (NGX_THREADS)
c[i].lock = ;
#endif
} while (i); cycle->free_connections = next;
cycle->free_connection_n = cycle->connection_n; /* for each listening socket */ ls = cycle->listening.elts;
for (i = ; 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, ) == 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) == -) {
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);
...... }
Nginx源码研究三:Epoll在NGINX中的使用的更多相关文章
- Chrome自带恐龙小游戏的源码研究(三)
在上一篇<Chrome自带恐龙小游戏的源码研究(二)>中实现了云朵的绘制和移动,这一篇主要研究如何让游戏实现昼夜交替. 昼夜交替的效果主要是通过样式来完成,但改变样式的时机则由脚本控制. ...
- Nginx源码研究七:nginx的location指令分析
在nginx的配置文件nginx.conf中,我们在配置server的时候,会配置一下location指令,这个location指令是提供给用户来配置对于符合指令的http请求,采用该指令内部的处理方 ...
- Nginx源码研究一:NGINX模块启动
Nginx 是一个轻量级,但是高性能的 HTTP 和 代理 服务器,也是一个 IMAP/POP3/SMTP代理服务器. 它的第一个版本0.1.0是由俄罗斯的工程师Igor Sysoev与2004年10 ...
- Nginx源码研究六:NGINX的配置文件分析
上一篇写到nginx的各个模块的配置信息的存储结构,大体描述了对配置信息的配置项生成,定制,初始化过程.这里重点研究实现定制的过程,所谓实现定制,这里指的是,nginx系统提供使用者定义nginx的配 ...
- [nginx] nginx源码分析--proxy模式下nginx的自动重定向auto_redirect
描述 我们配置了一个proxy模式下的nginx, upstream backend-test { server ; } server { listen ; location = /nginx/hww ...
- Nginx源码研究二:NGINX的事件处理概论
NGINX作为服务端的应用程序,在客户端发出数据后,服务端在做着这样一些处理,数据先会经过网卡,网卡会和操作系统做交互,经过操作系统的协议栈处理,再和不同的应用程序交互. 在这里面涉及两个概念,一个是 ...
- Nginx源码研究五:NGINX的配置信息管理
配置信息是nginx系统重要的组成部分,配置信息的使用,实际上包含两层,一层是用户针对参数定义了值,例如下面nginx参数文件中的 keepalive_timeout 65,还有一部分是用户没有定义值 ...
- Nginx源码研究八:nginx监听socket实现流程
前面描述了nginx系统分析nginx的配置文件,初始化模块相关参数的过程,这里利用nginx监听socket的实现过程,做一次完整的回顾 1.首先,nginx启动的main函数中,会先初始化cycl ...
- Nginx源码研究四:NGINX的内存管理
关于nginx的内存使用,我们先看代码,下面是nginx_cycle.c中对全局数据结构cycle的初始化过程 pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, ...
随机推荐
- 哈希集合——hashSet
/** 哈希集合特点:存取顺序不确定,同一个哈希值的位置可以存放多个元素, 哈希集合存放元素的时候是先判断哈希地址值:hashCode()是否相同,如果不同 ...
- BZOJ 1020 [SHOI2008]安全的航线flight
1020: [SHOI2008]安全的航线flight Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 847 Solved: 286[Submit][ ...
- C#之VS2010ASP.NET页面调用Web Service和winform程序调用Web Service
一:用ASP.NET调用Web Service 打开VS2010,打开“文件-新建-网站”,选择“ASP.NET网站” 选好存储位置,语言后点击确定,进入默认页面.然后先添加Web引用,把WebSer ...
- mapreduce框架详解【转载】
[本文转载自:http://www.cnblogs.com/sharpxiajun/p/3151395.html] 开始聊mapreduce,mapreduce是hadoop的计算框架,我学hadoo ...
- js打开新的链接下载文件
var p =params.join("&"); var a = document.createElement('a'); a.href = 'report/exportp ...
- WEB组件之间的关系
WEB组件之间的关系: A:重定向的特点: 1:发生客户端 2:地址栏发生变化 3:两个WEB组件不共享request的数据. 4 重定向只能传递文本类型数据 服务端的方法:response.send ...
- 级联分类器训练-----OpenCV
关键词:级联分类器.opencv_traincascade 下面简述操作过程: 准备正负样本:neg.pos 正负样本路径生成:dir /a/b>path.txt //path:pos or n ...
- 你需要知道的九大排序算法【Python实现】之插入排序
三.插入排序 基本思想:插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的.个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2).是稳定的排序方法.插入算 ...
- NIO Socket非阻塞模式
NIO主要原理和适用 NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的socketchannel告诉Selector,我们接着做别的事情,当有 事件发生时,他会通知我们 ...
- cocoa Touch-UIKit
1. 简介: UIKitk框架提供一系列的Class(类)来建立和管理iPhone OS应用程序的用户界面( UI )接口.应用程序对象.事件控制.绘图模型.窗口.视图和用于控制触摸屏等的接口. (P ...