跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

Nginx源码实战:ngx_http_write_filter_module数据发送链逻辑

ngx_http_write_filter_module 是 HTTP 响应体发送链的最终一环,负责将上游模块产生的 ngx_chain_t 缓冲区链表写入 socket;它不直接 I/O,而是调用 ngx_linux_sendfile 或 ngx_writev,协调写事件、缓冲区推进与连接状态,并在阻塞时挂起等待事件驱动重试。 nginx 的
ngx_http_write_filter_module
是 HTTP 响应体发送链的最终一环,负责将上游模块产生的缓冲区(
ngx_chain_t
)真正写入连接的 socket。它不直接做网络 I/O,而是调用
ngx_linux_sendfile
、
ngx_writev
等底层发送函数,并协调写事件、缓冲区管理与连接状态。 write filter 的位置与职责 该模块是 HTTP 输出过滤链(output filter chain)的末端,位于所有其他 body filter 模块(如 gzip、chunked、range 等)之后。它的核心任务包括: 检查当前连接是否可写(
c->write->ready
)、是否处于关闭或错误状态 遍历传入的
ngx_chain_t *
链表,跳过已发送完成的缓冲区(
buf->pos == buf->last
) 尝试一次性发送尽可能多的未发送数据(合并为 sendfile 或 writev 调用) 处理部分发送(partial write):更新
buf->pos
,保留剩余缓冲区继续挂起 若发送受阻(EAGAIN/EWOULDBLOCK),则注册写事件并返回
NGX_AGAIN
,等待下次事件驱动回调 关键数据结构与流程入口 入口函数是
ngx_http_write_filter
,原型为: ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in); 其中:
r
是当前请求,通过
r->connection
获取连接对象
c
in
是上游模块传来的待发送缓冲区链表(可能含内存 buf 或文件 buf) 函数内部会把
in
合并到
r->out
(当前待发链表),再统一调度发送 实际发送由
ngx_http_writer
(在 event handler 中触发)调用
ngx_http_write_filter
启动,形成“事件驱动 → 尝试发送 → 阻塞则挂起 → 再次就绪再发”的闭环。 sendfile 与 writev 的选择逻辑 nginx 根据缓冲区类型和系统能力自动选择最优发送方式: 若链表中存在
buf->in_file == 1
且满足条件(如无前导内存 buf、文件对齐、非 SSL 连接等),优先走
ngx_linux_sendfile
否则使用
ngx_writev
(封装
writev()
系统调用),将多个内存 buf 合并为一次 syscall SSL 连接强制禁用 sendfile,全部走 writev + OpenSSL BIO 写入 这个判断发生在
ngx_http_write_filter
内部的
ngx_http_output_filter
下游调用中,由
ngx_http_top_body_filter
统一调度。 缓冲区生命周期与内存管理 write filter 不分配也不释放 buf 内存,只推进
pos
指针: 每个
ngx_buf_t
的
pos/last
描述当前待发区间;发送后更新
pos
,若
pos == last
则标记该 buf 已完成 整条链表发送完毕后,
r->out
被清空,buf 可由上游模块回收(例如 upstream 模块在
ngx_http_upstream_process_non_buffered_downstream
中释放) 若连接断开或请求终止,未发送完的 buf 会被
ngx_http_finalize_request
清理,避免泄漏

相关文章