1 定义ngx_http_request_handler 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request.cstaticvoidngx_http_request_handler(ngx_event_t*ev){ngx_connection_t*c;ngx_http_request_t*r;cev-data;rc-data;ngx_http_set_log_request(c-log,r);ngx_log_debug2(NGX_LOG_DEBUG_HTTP,c-log,0,http run request: \%V?%V\,r-uri,r-args);if(c-close){r-main-count;ngx_http_terminate_request(r,0);ngx_http_run_posted_requests(c);return;}if(ev-delayedev-timedout){ev-delayed0;ev-timedout0;}if(ev-write){r-write_event_handler(r);}else{r-read_event_handler(r);}ngx_http_run_posted_requests(c);}ngx_http_request_handler 函数 是 Nginx HTTP 模块的核心事件回调。 它作为一个 请求事件分发器根据事件的读写类型 将请求分发到当前阶段注册的对应读写处理函数中 同时处理连接关闭、限速延迟超时等特殊状态 并最终驱动该连接上的待执行请求从而将事件驱动机制与 HTTP 请求的状态机干净地解耦。2 详解1 函数签名staticvoidngx_http_request_handler(ngx_event_t*ev)返回值 函数不返回任何值 该函数是一个事件处理回调由 Nginx 的事件驱动机制如 epoll_wait 循环调用。 事件回调的设计原则是“处理完毕后即返回”无需向调度者反馈结果。参数 ngx_event_t *ev 当前被触发的事件1 获取连接与请求上下文 2 日志 3 连接是否需要关闭 4 清除延迟/超时标志 5 根据事件类型分发处理 6 运行本连接上积压的挂起请求1 获取连接与请求上下文{ngx_connection_t*c;ngx_http_request_t*r;cev-data;rc-data;获取 当前的 连接和事件2 日志ngx_http_set_log_request(c-log,r);ngx_log_debug2(NGX_LOG_DEBUG_HTTP,c-log,0,http run request: \%V?%V\,r-uri,r-args);3 连接是否需要关闭if(c-close){r-main-count;ngx_http_terminate_request(r,0);ngx_http_run_posted_requests(c);return;}检查连接是否已被标记为需要关闭 c-close 是一个标志位由上层逻辑在检测到连接应当终止时设置 此处先检查该标志是因为一旦连接标记关闭就没有必要再进行正常的读写处理。 这是一种快速失败路径避免在即将关闭的连接上做无效操作。 如果该标志已设置则进入关闭处理分支 否则跳过该分支继续后续正常事件处理。将主请求的引用计数加 1 这里人为地递增 count 是为了防止在随后调用的 ngx_http_terminate_request 内部由于某些操作比如子请求结束 导致 count 被减到 0从而提前释放主请求的相关资源。 这是一种保护性计数保证在终止过程中主请求对象仍然有效。 在 ngx_http_terminate_request 执行完毕后 对应的引用会在适当位置被减回去启动请求的终止流程。 参数 0 表示终止原因码 这里为 0 通常表示“由于连接关闭而终止” 与正常的请求处理完成会传 NGX_OK 或 NGX_ERROR 等区分开。 该函数会执行一系列清理工作并最终调用 ngx_http_finalize_request 将请求状态置为完成。 因为此时连接即将关闭所以直接对请求进行彻底清理确保不再有未释放的资源。运行当前连接上被挂起的 “posted 请求” 链表4 清除延迟/超时标志if(ev-delayedev-timedout){ev-delayed0;ev-timedout0;}判断当前事件是否同时具有 delayed延迟和 timedout超时标志 delayed 标志用于限速功能limit_rate。 当需要减缓发送速度时Nginx 会将写事件的触发时间推迟到未来的某个时间点并设置 delayed 1。 timedout 标志表示事件是由于定时器超时而触发的。 在某些情况下一个延迟事件到期时其内部定时器也可能恰好超时导致事件同时带有这两个标志。 若不清除可能会干扰后续处理逻辑 因此这里检查并清除它们让事件恢复为“普通”的就绪状态。5 根据事件类型分发处理if(ev-write){r-write_event_handler(r);}else{r-read_event_handler(r);}判断当前事件是读事件还是写事件 是写事件调用请求当前阶段注册的写事件处理函数并将请求本身作为参数传入 否则调用请求当前阶段注册的读事件处理函数并将请求作为参数传入6 运行本连接上积压的挂起请求ngx_http_run_posted_requests(c);}本次读写事件处理完毕后 运行当前连接上被挂起的 posted 请求链表