转自:http://blog.csdn.net/spch2008/article/details/29803719
Nginx 自己维护了一个时间,用户向用户提供时间,它使用缓存时间的机制,这样避免了频繁的系统调用(gettimeofday),加快处理速度。
但缓存时间,又必须要及时更新时间,否则时间将不准确。所以, NGINX配套了一系列的措施,减少误差。
点击(此处)折叠或打开
-
void
-
ngx_process_events_and_timers(ngx_cycle_t *cycle)
-
{
-
ngx_uint_t flags;
-
ngx_msec_t timer, delta;
-
-
if (ngx_timer_resolution) {
-
timer = NGX_TIMER_INFINITE; //-1
-
flags = 0;
-
-
} else {
-
timer = ngx_event_find_timer();
-
flags = NGX_UPDATE_TIME;
-
}
-
-
(void) ngx_process_events(cycle, timer, flags);
-
}
暂时不去理会ngx_timer_resolution,只关注else部分,timer = ngx_event_find_timer(),该函数返回距离第一个超时事件还有多久时间,可能为-1,即目前没有注册超时事件。而同时,flags 标记为NGX_UPDATE_TIME,即更新缓存时间。
ngx_process_events对应于具体的事件处理函数,本文以epoll为例,因而对应于如下代码:
点击(此处)折叠或打开
-
static ngx_int_t
-
ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
-
{
-
events = epoll_wait(ep, event_list, (int) nevents, timer);
-
-
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
-
ngx_time_update();
-
}
-
}
timer为epoll_wait等待的最大时间,即epoll_wait返回后,由于flags被设置为NGX_UPDATE_TIME,因而,调用ngx_time_update进行缓存时间的更新。
上面带来了一个新问题,如果,timer 为-1或者过大,而epoll_wait又没有获得可用套接字,那么,此时,时间很久得不到更新,导致误差过大。
因而,nginx引入了一个强制更新的策略。
点击(此处)折叠或打开
-
if (ngx_timer_resolution) {
-
timer = NGX_TIMER_INFINITE; //-1
-
flags = 0;
-
}
ngx_timer_resolution 为用户配置的参数值,即ngx_timer_resolution时间过后,必须进行时间的更新,这样防止时间长时间的不到更新。
timer = -1, 这样,epoll_wait 会无穷阻塞。
-
static ngx_int_t
-
ngx_event_process_init(ngx_cycle_t *cycle)
-
{
-
if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) {
-
struct sigaction sa;
-
struct itimerval itv;
-
-
sa.sa_handler = ngx_timer_signal_handler;
-
if (sigaction(SIGALRM, &sa, NULL) == -1) {}
-
-
if (setitimer(ITIMER_REAL, &itv, NULL) == -1) {}
-
}
-
}
首先注册一个信号(SIGALRM)处理函数,然后设定一个计时器setitimer, 在(timer_resoluiton)时间超时后,发送SIGALRM事件,那么事件处理函数究竟完成了一个什么样的功能?
点击(此处)折叠或打开
-
void
-
ngx_timer_signal_handler(int signo)
-
{
-
ngx_event_timer_alarm = 1;
-
}
仅仅将ngx_event_timer_alarm置1。有一个知识点:信号中断系统调用。因而,SIGALRM会中断epoll_wait的调用,epoll_wait返回后,errno设置为EINTR。
点击(此处)折叠或打开
-
events = epoll_wait(ep, event_list, (int) nevents, timer);
-
-
if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
-
ngx_time_update();
-
}
这里,ngx_event_timer_alarm已经在信号处理函数中被设置为1, 因此,会执行时间更新。既然有强制刷新策略,为嘛还要第一种策略呢?我觉得是这样,首先这算是一个优化措施,而
nginx要保证最少配置即可使用,所以,此配置项可以不用进行配置。不同场景有不同的配置,频繁访问的网站,不需要timer_resolution,epoll_wait会迅速返回,时间可以及时更新。
阅读(1328) | 评论(0) | 转发(0) |