Nginx的超时处理
Nginx事件管理主要是网络事件和定时器事件。下面介绍定时器事件管理,即所谓的超时处理。
1. 为什么进行超时处理
Nginx有必要对可能发生超时的事件进行统一管理,并在事件超时时作出相应的处理,比如回收资源,返回错误等。举例来说,当客户端对nginx发出请求连接后,nginx机会accept()并建立对应的连接对象、读取额护短请求的头部信息。而读取这个头部信息显然是要在一定的时间内完成的。如果在一个有限的时间内没有读取到头部信息或者读取读取的头部信息不完整,那么nginx就无法进行正常处理,并且认为这是一个错误/非法的请求,直接返回错误信息并释放相应资源,如果nginx不这样做,那么针对如此的恶意攻击就和容易实施。
2. 如何进行超时处理
nginx对于是否存在有超时事件的处理很巧妙。首先,nginx利用红黑树来组织那些等待处理的并且需要关注其是否超时的事件对象(以下称该红黑树为事件计时红黑树:event_timer_rbtree);其次,nginx提供了两种方案来检测那些等待处理的事件对象是否已经超时,一种为常规的定时检测机制,也就是设置定时器,每过一定的时间就对红黑树管理的所有事件对象进行一次超时检测;另一种是过距离当前最快发生超时的事件对象的时间就进行一次超时检测。
3. nginx中超时处理的实现
超时事件对象的数据结构组织
我们已经知道nginx把事件封装在一个名为ngx_event_s的结构体内,而该结构体有几个字段与本节讲的nginx超时处理相关。
unsigned timedout:1;
unsigned timer_set:1;
ngx_rbtree_node_t timer;
timedout域字段,用于标识该当前事件是否已经超时,0为没有超时。
timer_set域字段,用于标识该当前事件是否已经加入到红黑树,需要对其是否超时做监控,0为没有加入。
tmer字段,很容易看出属于红黑树节点类型变量,红黑树就是通过该字段来组织事件对象。
nginx设置了两个全局变量以便在程序的任何地方都能快速的访问到事件计时红黑树:
ngx_thread_volatile ngx_rbtree_t ngx_event_timer_rbtree;
static ngx_rbtree_node_t ngx_event_timer_sentinel;
它们都定义在源文件ngx_event_timer.c内,结构体ngx_rbtree_s类型的全局变量ngx_event_timer_rbtree封装了事件计时红黑树树结构,而ngx_event_timer_sentinel属于红黑树节点类型变量,在红黑树的操作过程中当作哨兵使用,同时它是static的,所以作用域仅限于模块内。