Worker 進程主循環:
for (;;) {
if (ngx_exiting) break;
ngx_process_events_and_timers(cycle); // 核心:事件+定時器
// 信號處理...
}
void ngx_process_events_and_timers(ngx_cycle_t *cycle) {
ngx_msec_t timer = ngx_event_find_timer(); // 獲取最近定時器超時時間
ngx_process_events(cycle, timer, flags); // epoll_wait(timer)
ngx_event_expire_timers(); // 處理過期定時器
}
ngx_rbtree_t,鍵為 ngx_msec_t(毫秒級絕對過期時間)left/right/parent/color/key,節點嵌入 ngx_event_t 中// 初始化階段
ngx_event_process_init() {
// 設置 interval timer,如 100ms 一次 SIGALRM
struct itimerval itv = {{0, 100*1000}, {0, 100*1000}};
setitimer(ITIMER_REAL, &itv, NULL);
signal(SIGALRM, ngx_timer_signal_handler);
}
// 信號處理函數
void ngx_timer_signal_handler(int signo) {
ngx_event_timer_alarm = 1; // 只置標誌,不做複雜操作
}
流程:信號中斷 epoll_wait → 返回 -1/EINTR → ngx_process_events 返回 → ngx_time_update() 更新時間緩存 → ngx_event_expire_timers() 處理過期定時器。
setitimer 精度受限於系統時鐘中斷(通常 1-10ms),高頻定時器開銷大epoll_wait 返回ngx_msec_t ngx_event_find_timer() {
ngx_rbtree_node_t *node = ngx_rbtree_min(timer_root);
if (node) return (ngx_msec_t)node->key - ngx_current_msec;
return NGX_TIMER_INFINITE; // 無定時器,永久等待
}
// 主循環調用
timer = ngx_event_find_timer();
n = epoll_wait(ep, events, max, timer); // timer 為最近定時器剩餘毫秒數
ngx_time_update(); // epoll_wait 返回後立即更新時間
ngx_event_expire_timers(); // 處理過期
epoll_wait 內核級超時,精度可達亞毫秒高頻 IO 時每次 epoll_wait 返回都調用 ngx_time_update()(系統調用 gettimeofday/clock_gettime),但現代內核 vDSO 機制使其極廉價(用戶態讀取內核映射頁,無上下文切換)。
Nginx 默認啟用 epoll_wait 超時模式,信號模式作為補充或舊系統兼容。關鍵配置:
// ngx_event_timer_alarm 只有在使用 timer_signal 時才會被檢查
// 現代 Linux 完全依賴 epoll_wait timeout
// 代碼片段:
if (ngx_event_timer_alarm) {
ngx_event_timer_alarm = 0;
ngx_time_update();
ngx_event_expire_timers();
}
| 維度 | 信號模式 | epoll_wait 超時模式 |
|---|---|---|
| 實現複雜度 | 需信號處理、鎖保護 | 純事件循環,簡潔 |
| 定時精度 | 受限於 timer interval (∼ms) | 內核級超時 (∼μs) |
| CPU 開銷 | 固定間隔中斷,無負載也消耗 | 按需喚醒,無定時器則無開銷 |
| 可擴展性 | 信號處理函數受限(只能置標誌) | 無特殊限制 |
| 適用場景 | 無 epoll/kqueue 的舊系統 | 現代高性能服務器(默認) |
CLOCK_MONOTONIC 避免系統時間回撥導致定時器提前/延遲觸發ngx_event_expire_timers 一次遍歷處理所有過期節點,避免逐個系統調用Nginx 定時器以紅黑樹組織、epoll_wait 超時驅動為核心,實現了高精度、低開銷、統一事件循環的定時調度。信號模式作為歷史兼容保留。理解其時間源更新時機、紅黑樹操作、雙模式權衡,對設計高性能網絡框架、遊戲服務器定時器、任務調度系統具有重要參考價值。