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,原型为:
其中:
-
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清理,避免泄漏

















