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