Nginx四层与七层协议栈共享事件循环但严格隔离:四层(stream模块)基于连接透传,走ngx_stream_init_connection→session_handler→proxy_process;七层(http模块)按11阶段链处理请求,核心在ngx_http_init_request→find_config→content阶段,location匹配为分发关键点。

理解 Nginx 源码中四层与七层协议栈的处理分发流程,关键在于厘清其模块化设计中的“事件驱动 + 分层抽象”机制:四层(TCP/UDP)由 ngx_event_module 和 ngx_stream_module 主导,关注连接生命周期与数据透传;七层(HTTP/HTTPS)由 ngx_http_module 主导,聚焦请求解析、路由、内容生成与响应封装。两者共享核心事件循环(epoll/kqueue),但协议解析、上下文构建、阶段处理完全隔离。
四层转发(stream 模块)的核心路径
stream 模块用于 TCP/UDP 代理(如数据库、Redis、TLS 直通),不解析应用层内容,只做连接级调度:
-
入口在
ngx_stream_init_connection():当 accept 完成后,为新连接创建ngx_stream_session_t,绑定到 event loop -
读写事件触发
ngx_stream_session_handler():根据当前状态(waiting、reading、writing)调用对应 handler,例如ngx_stream_proxy_init()启动后端连接 -
数据转发无解析:使用
ngx_stream_proxy_process_connection()在上下游 socket 间直接 memcpy 数据(buffered copy),仅做流量控制和超时管理 -
配置驱动分发:通过
stream { server { ... } }块定义监听地址+端口,匹配靠ngx_stream_core_server_conf_t的 listen 配置,不涉及 URI 或 Host 匹配
七层处理(http 模块)的典型阶段链
HTTP 模块深度解析协议语义,按预定义的 11 个处理阶段(phases)依次执行,每个阶段可注册多个 handler:
-
阶段起点是
ngx_http_init_request():从ngx_http_wait_request_handler()接收已建立连接,解析首行与头部,构建ngx_http_request_t - 核心阶段包括:post_read(读完请求体后)、server_rewrite(重写 server_name)、find_config(匹配 location)、rewrite(URI 重写)、access(权限检查)、content(生成响应主体)等
-
location 匹配是关键分发点:在
ngx_http_core_find_location()中遍历所有ngx_http_core_loc_conf_t,按 prefix / regex / exact 顺序匹配 URI,决定后续 handler 链 -
content 阶段最终落点:若未显式配置 content handler(如 proxy_pass、php-fpm),则默认用
ngx_http_static_handler()返回文件;否则交由对应模块(如ngx_http_proxy_handler())发起 upstream 请求
共用基础设施与关键隔离点
尽管分属不同协议栈,Nginx 仍复用大量底层设施,但严格隔离协议语义处理:
-
共享事件引擎:
ngx_event_t、ngx_connection_t是四层与七层共同基类;读写事件回调函数指针(read->handler,write->handler)在连接初始化时被设为 stream 或 http 对应的 handler -
连接与请求分离:一个
ngx_connection_t可能承载多个 HTTP 请求(keepalive),但只对应一个 stream session;HTTP 的ngx_http_request_t是逻辑请求单位,而 stream 的ngx_stream_session_t是连接单位 -
配置解析完全独立:conf 文件中
http{}与stream{}是平行块,分别由ngx_http_block()和ngx_stream_block()解析,生成各自 conf struct,无交叉引用 -
内存上下文隔离:stream 使用
ngx_stream_conf_ctx_t管理配置,http 使用ngx_http_conf_ctx_t;二者均挂载在 cycle->conf_ctx 数组中,索引由模块 index 区分
调试与验证建议
想快速验证源码路径,可结合日志与断点定位关键函数:
- 编译时加
--with-debug,在配置中开启error_log logs/error.log debug;,观察 “*xx http init request” 或 “*xx stream init connection” 日志 - 对四层调试,在
ngx_stream_init_connection和ngx_stream_proxy_init下断点;对七层,在ngx_http_init_request和ngx_http_core_content_phase下断点 - 注意
ngx_connection_t->data字段:HTTP 场景指向ngx_http_request_t*,stream 场景指向ngx_stream_session_t*,这是运行时区分协议栈的最直接依据


















