本章我们讲述一下nginx中event的实现。Nginx中的event对象ngx_event_t
提供了一种机制,能够通知程序发生了某个事件。这里的event主要包括两大种类:
1. 相关事件模块变量的声明
通常情况下,我们Linux操作系统支持select、poll、epoll这三种事件驱动机制。这里nginx启动时会根据当前event模块的配置选择恰当的事件驱动。
2. 相关静态函数声明
3. 相关变量定义
下面我们简要介绍一下这些字段:
- ngx_timer_resolution: 可以通过nginx配置文件主配置段中的
timer_resolution
指令来降低worker进程的定时器分辨率(timer resolution),这样就可以降低gettimeofday()系统调用的次数。默认情况下,gettimeofday()会在每一次收到kernel事件时被调用。我们可以通过降低timer resolution的值,这样gettimeofday()函数就会每隔interval
时间被调用一次。例如:
timer_resolution 100ms;
内部interval
的实现依赖于所使用的方法:
假如所采用的事件驱动机制是```kqueue```的话,使用EVFILT_TIMER filter来实现
假如所采用的事件驱动机制是```eventport```的话,使用timer_create()来实现
否则,采用setitimer()来实现
-
ngx_event_timer_alarm: 当收到SIGALARM
信号时,会将此变量置为1,以指示更新Nginx缓存时间
-
ngx_event_max_module: 当前属于NGX_EVENT_MODULE模块的个数
-
ngx_event_flags: 用于保存当前事件驱动机制
所支持的事件掩码
-
ngx_event_actions: 用于保存当前事件驱动机制下的actions函数
-
connection_counter/ngx_connection_counter: 用于统计当前的连接数
-
ngx_accept_mutex_ptr: 存放互斥量内存地址的指针
-
ngx_accept_mutex: accept互斥锁
-
ngx_use_accept_mutex: 表示是否需要通过对accept加锁来解决惊群问题。当nginx worker进程数大于1
时,且配置文件中开启了accept_mutex
时,这个标志置为1
-
ngx_accept_events: 表示在获取accept互斥锁的时候,是否还需要调用ngx_enable_accept_events()来使能accept events。通常采用eventport
这一事件驱动机制时才需要。
-
ngx_accept_mutex_held: 用于指示当前是否拿到了锁
-
ngx_accept_mutex_delay: 当accept_mutex
被启用的话,如果当前有另一个worker进程正在accept新连接(connections),则当前worker进程最长会等待多长时间尝试重新开始accept新连接。其实就是获取互斥锁的最大延迟时间
-
ngx_accept_disabled: 用于控制当前worker进程是否参与获取ngx_accept_mutex
。一般在当前worker进程连接数过多时,就不会参与竞争,这样可以起到负载均衡的目的。
我们当前并不支持NGX_STAT_STUB
,该宏定义需要在启用HTTP_STUB_STATUS
编译选项时才会定义。请参看Module ngx_http_stub_status_module但是这里我们还是简单介绍一下各字段的含义。
-
ngx_stat_accepted0/ngx_stat_accepted: 用于统计当前nginx一共accept多少连接
-
ngx_stat_handled0/ngx_stat_handled: 用于统计当前所处理的总的连接数。通常情况下,本字段的值与ngx_stat_accepted
字段的值相同,除非达到了一些资源的限制(例如,worker_connections的限制)
-
ngx_stat_requests0/ngx_stat_requests: 用于统计客户端总的请求数
-
ngx_stat_active0/ngx_stat_active: 用于统计当前处于active状态的客户端连接数,这也包括Waiting
状态的连接
-
ngx_stat_reading0/ngx_stat_reading: 当前Nginx正在读取请求头
(request header)的连接数
-
ngx_stat_writing0/ngx_stat_writing: 当前nginx正在向客户端回写应答
(write the response back)的连接数
-
ngx_stat_waiting0/ngx_stat_waiting: 当前正处于空闲状态的客户端连接数。
4. event module相关变量
下面简单介绍一下这些变量:
-
ngx_events_commands: nginx的events
命令
-
ngx_events_module_ctx: events模块上下文
-
ngx_events_module: nginx events模块
-
event_core_name: nginx 事件核心模块名称为event_core
-
ngx_event_core_commands: nginx事件核心模块命令
-
ngx_event_core_module_ctx: nginx事件核心模块上下文
-
ngx_event_core_module: nginx事件核心模块
5. 函数ngx_process_events_and_timers()
本函数作为nginx处理IO事件以及定时器事件的主入口函数。下面我们简要分析一下函数的实现:
6. 函数ngx_handle_read_event()
本函数用于向nginx事件驱动机制登记为读事件。通常在连接建立或者读取完一次数据之后,需要再调用一次本函数。下面简要介绍一下函数的实现:
注意: Nginx中事件驱动机制底层
有些支持边沿触发,有些只支持水平触发。但是在Nginx上层统一都采用边沿触发。以降低事件的通知频率,提高整体系统性能。
7. 函数ngx_handle_write_event()
本函数用于向nginx事件驱动机制登记为写事件。通常在连接建立或者连接当前不处于写状态时,需要再调用一次本函数。下面简要介绍一下函数的实现:
8. 函数ngx_event_init_conf()
此函数会在nginx event模块初始化时被调用。下面简要介绍一下本函数的调用流程:
9. 函数ngx_event_module_init()
此函数作为nginx event核心模块的初始化函数,会在nginx中所有模块(nginx core模块、http模块、event模块、upstream模块等)都完成之后,在ngx_init_cycle()中被调用:
ngx_init_cycle(){
ngx_init_modules();
}
下面我们就简要介绍一下本函数的实现:
如下是各全局共享内存变量在内存中的示意图:
10. 函数ngx_timer_signal_handler()
此函数作为SIGALRM
信号的处理函数。
11. 函数ngx_event_process_init()
此函数作为nginx event core模块的init_process
回调函数,一般会在worker进程初始化时被调用。下面我们简要介绍一下本函数的执行流程:
12. 函数ngx_send_lowat()
本函数用于设置socket的SO_SNDLOWAT
选项,用于指示socket在发送缓冲区中可用空间大于sndlowat
时提示socket可写。我们当前不支持NGX_HAVE_LOWAT_EVENT
宏定义。
13. 函数ngx_events_block()
本函数作为nginx配置文件中解析到events{}
指令时的回调函数。下面我们简要讲述一下本函数的实现:
nginx event模块上下文在cycle->conf_ctx中的内存图景:
14. 函数ngx_event_connections()
用于解析events{}中的worker_connections
指令。该指令配置语法如下:
Syntax: worker_connections number;
Default:
worker_connections 512;
Context: events
15. 函数ngx_event_use()
本函数用于解析events{}配置模块的use
指令。该指令的配置语法是:
Syntax: use method;
Default: —
Context: events
method的值可以为select、poll、epoll…
解析use
指令时,如果当前nginx是以NGX_PROCESS_SINGLE模式工作,要求所采用事件驱动机制的ctx_index没有改变。
16. 函数ngx_event_debug_connection()
本函数用于解析events{}配置模块的debug_connection
指令。该指令的配置示例如下:
events {
debug_connection 127.0.0.1;
debug_connection localhost;
debug_connection 192.0.2.0/24;
debug_connection ::1;
debug_connection 2001:0db8::/32;
debug_connection unix:;
...
}
本函数分别解析三种不同类型的配置:
-
unix域socket
-
cidr格式配置的地址
-
通过主机名配置的地址
17. 函数ngx_event_core_create_conf()
本函数作为nginx event core模块上下文在创建时候执行的回调函数,会在ngx_events_block()函数中被调用,此处主要是创建event core模块的配置上下文结构:ngx_event_conf_t
18. 函数
本函数作为nginx event core模块上下文在初始化时候执行的回调函数,会在ngx_events_block()函数中被调用,此处主要是给ngx_event_conf_t
赋默认值。这里特别注意选择默认事件驱动机制的处理
[参看]
-
nginx events
-
nginx event 模块解析
-
Nginx学习笔记(十八):事件处理框架
-
事件和连接
-
eventfd 的分析与具体例子
-
EVENTFD
-
Nginx源码分析 - Event事件篇 - Event模块和配置的初始化
-
文章5:Nginx源码分析–事件循环
-
Nginx学习之十-超时管理(定时器事件)
-
GNU Linux中的SO_RCVLOWAT和SO_SNDLOWAT说明