1 定义 ngx_http_request_handler 函数 定义在 ./nginx-1.24.0/src/http/ngx_http_request.cstatic void ngx_http_request_handler ( ngx_event_t * ev) { ngx_connection_t * c; ngx_http_request_t * r; c= ev-> data; r= c-> 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-> delayed&& ev-> timedout) { ev-> delayed= 0 ; ev-> timedout= 0 ; } 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 函数签名 static void ngx_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; c= ev-> data; r= c-> 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-> delayed&& ev-> timedout) { ev-> delayed= 0 ; ev-> timedout= 0 ; } 判断当前事件是否同时具有 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 请求链表