Mind and Hand Help

Nginx Lua Lifecycle

1. Nginx 进程生命周期

Nginx 启动 → Master 进程 → Fork Worker → Worker 处理请求 → Worker 退出 → Master 退出。

在这个过程中,Lua 脚本可能运行在 配置阶段、进程启动阶段、请求处理阶段、定时器/异步阶段

2. Lua 执行生命周期阶段

(1) 配置阶段

  • init_by_lua/init_by_lua_file

    • 发生在 master 进程加载配置时(nginx -s reload 也会触发)

    • 全局只执行一次,适合初始化全局 Lua 环境、加载模块、预热缓存等

    • 注意:此时不能用 ngx.* 请求相关 API(因为没有请求上下文)

(2) Worker 初始化阶段

  • init_worker_by_lua/init_worker_by_lua_file

    • 每个 worker 进程启动时执行一次

    • 用来启动定时器(ngx.timer.at )、初始化 worker 级别状态

    • 同样不能用请求相关的 API,但可以用 cosocket API 连接数据库、Redis 等。

(3) 请求处理阶段(核心生命周期)

当请求进入 worker 时,Lua 脚本可挂在不同阶段:

  • set_by_lua

    • 执行在 rewrite 阶段之前,用于设置变量。

    • 要求必须返回值,执行环境有限制。

  • rewrite_by_lua

    • 在 rewrite 阶段运行,可改写 URI、做路由逻辑。

    • 可以使用大部分 ngx.* API。

  • access_by_lua

    • 在 access 阶段运行,可做鉴权、限流

    • 若调用 ngx.exit(403) 等可中止请求。

  • content_by_lua

    • 生成响应的主要阶段。

    • 可以写响应体、调用上游接口、反向代理等。

    • 最完整的请求上下文。

  • header_filter_by_lua

    • 在返回响应头时执行,可以修改响应头。

    • 无法再写响应体。

  • body_filter_by_lua

    • 在发送响应体时执行,可以修改响应体(比如做压缩/替换)。

    • 数据是流式的,可能分多次调用。

  • log_by_lua

    • 在请求完成后执行(log 阶段),适合写日志、打点。

    • 不影响请求结果,但仍有请求上下文。

(4) 请求外的异步生命周期

  • Timer 回调 (ngx.timer.at)

    • 在 worker 内调度执行,独立于请求上下文。

    • 可用于周期任务,如心跳、定时清理。

  • Light thread (coroutine)

    • ngx.thread.spawn 启动的“轻线程”,和请求生命周期绑定,请求结束后会被杀掉。

  • Cosocket API (ngx.socket.tcp, ngx.req.socket)

    • 支持非阻塞 IO,生命周期跟随请求(除非在定时器里)。

(5) Worker/进程退出阶段

  • 没有专门的 exit_worker_by_lua 钩子

    • Worker 退出时不会显式调用 Lua 脚本。

    • 如果需要清理,可以靠定时器或 log_by_lua 做善后。

3. 生命周期总结

Nginx master start └── init_by_lua (once per master) Worker start └── init_worker_by_lua (once per worker) Request start ├── set_by_lua ├── rewrite_by_lua ├── access_by_lua ├── content_by_lua ├── header_filter_by_lua ├── body_filter_by_lua └── log_by_lua Background ├── timer callbacks ├── cosocket operations └── light threads Worker exit └── (no direct lua hook)
27 January 2026