9.7.2 缓存时间的精度

上文简单地介绍过缓存时间的更新策略,它是与ngx_epoll_process_events方法的调用频率及其flag参数相关的。实际上,Nginx还提供了设置更新缓存时间频率的功能(也就是至少每隔timer_resolution毫秒必须更新一次缓存时间),通过在nginx.conf文件中的timer_resolution配置项可以设置更新的最小频率,这样就保证了缓存时间的精度。

下面看一下timer_resolution是如何起作用的。在图9-4的第5步中,ngx_event_core_module模块初始化时会使用setitimer系统调用告诉内核每隔timer_resolution毫秒调用一次ngx_timer_signal_handler方法。而ngx_timer_signal_handler方法则会将ngx_event_timer_alarm标志位设为1,这样一来,一旦调用ngx_epoll_process_events方法,如果间隔的时间超过timer_resolution毫秒,肯定会更新缓存时间。

但如果很久都不调用ngx_epoll_process_events方法呢?例如,远超过timer_resolution毫秒的时间内ngx_epoll_process_events方法都得不到调用,那时间精度如何保证呢?在这种情况下,Nginx只能从事件模块对ngx_event_actions中process_events接口的实现来保证时间精度了。process_events方法的第2个参数timer表示收集事件时的最长等待时间。例如,在epoll模块下,这个timer就是epoll_wait调用时传入的超时时间参数。如果没有设置timer_resolution,一般情况下,process_events方法的timer参数都是大于0且小于500毫秒的值,而如果在设置了timer_resolution后,这个timer参数就是-1,它表示如果epoll_wait等调用检测不到已经发生的事件,将不等待而是立刻返回,这样就控制了时间精度。当然,如果某个事件消费模块的回调方法执行时占用的时间过长,时间精度还是难以得到保证的。