nginx 不支持用户主动提交异步任务,其“异步”仅面向 i/o 事件,通过 epoll/kqueue 监听就绪状态、非阻塞 i/o 分阶段处理请求、红黑树定时器和状态机驱动实现类异步行为,无任务队列或 await 支持。

Nginx 本身不支持用户主动提交异步任务,比如像 Node.js 的 setTimeout()、Promise.then(),或 Python 的 asyncio.create_task() 那样把自定义逻辑“排队”进一个任务队列等待执行。它的“异步”是面向 I/O 的,不是面向用户业务逻辑的。
换句话说:Nginx 的异步事件驱动架构,不提供任务提交接口,只提供事件响应能力。所谓“高效任务处理”,其实是把网络请求生命周期拆解为多个可中断、可恢复的 I/O 事件阶段,并在每个就绪时刻精准调度对应逻辑——它不排队任务,而是响应事件。
Nginx 中没有传统意义上的“任务提交”
- 没有全局任务队列(task queue)、microtask 队列或协程调度器
- 不允许你在 handler 中
await自定义函数,也不能post_task(...)提交回调 - 所有业务逻辑(如 header 解析、proxy 转发、日志写入)都必须在事件回调中同步完成,或通过状态机挂起等待下次事件
因此,“任务异步提交”这个说法在 Nginx 原生语境下是个误解。真正能做的,是利用其事件机制模拟延迟、分阶段、非阻塞的行为。
真正可用的“类异步”手段
-
定时器(timer)
使用ngx_add_timer()注册超时回调,例如:- 关闭空闲 keepalive 连接
- 触发 upstream 重试
- 清理临时状态
底层基于红黑树管理,精度高、无额外线程开销
-
状态机驱动的分阶段处理
HTTP 请求被切分为多个事件阶段:-
NGX_HTTP_READ_REQUEST_STATE:读取请求行和 header -
NGX_HTTP_CONTENT_PHASE:执行 content handler(如 proxy_pass) -
NGX_HTTP_LOG_PHASE:记录日志
每个阶段完成后不阻塞,而是设置当前请求状态(如r->write_event_handler = ngx_http_upstream_process_upstream),等下次 write/read 事件触发再继续
-
-
upstream 异步转发
proxy_pass表面是一条指令,实际由多个事件 handler 协同完成:- 先发 request header → 注册 read event 等待 upstream 响应头
- 收到 header 后再决定是否收 body → 若启用 streaming,则边收边发给客户端
整个过程无等待、无线程、全在单 worker 内靠事件切换推进
-
流式响应透传(proxy_buffering off)
当后端返回 SSE 或 chunked 流式响应时,Nginx 可禁用缓冲,实现:- 收到一个 chunk 就立即转发一个 chunk
- 不攒全响应,不阻塞事件循环
这依赖proxy_http_version 1.1+chunked_transfer_encoding on+proxy_set_header Connection ''等配置协同生效
需要避开的“伪异步”陷阱
- ❌ 在 handler 中调用阻塞系统调用(如同步 DNS 查询、
read()读普通文件、system()执行命令)
会卡住整个 worker,所有连接停滞 - ❌ 使用
auth_request子请求处理流式接口
它强制同步等待子请求完成,彻底破坏流式 pipeline - ❌ 开启
proxy_buffering on处理长周期异步响应
导致响应被缓存,丢失实时性,甚至内存耗尽
Nginx 的高效,来自对操作系统能力的极致调用(epoll/kqueue、sendfile、TCP 优化),而不是靠抽象出一套用户可控的任务调度层。它把“并发”变成“事件密度管理”,把“异步”还原为“I/O 就绪即处理”。想让它“提交任务”,不如想清楚:这个逻辑能不能拆成事件?能不能挂起状态?能不能交给内核通知?











