apisix~OpenResty各阶段的介绍

一、Worker 启动阶段(非请求级)

阶段 作用
init_by_lua Master 进程启动时执行一次,用于加载模块、初始化全局配置
init_worker_by_lua 每个 Worker 进程启动时执行一次,用于定时器、连接池预热等
exit_worker_by_lua Worker 退出前执行,用于清理资源

二、HTTP 请求处理阶段(按顺序)

复制代码
客户端请求
    │
    ▼
┌─────────────────┐
│  1. POST_READ   │  读完请求头后
└────────┬────────┘
         ▼
┌─────────────────┐
│ 2. SERVER_REWRITE│  Server 级 rewrite(较少用)
└────────┬────────┘
         ▼
┌─────────────────┐
│  3. FIND_CONFIG │  匹配 server/location(内部阶段,一般无 Lua)
└────────┬────────┘
         ▼
┌─────────────────┐
│   4. REWRITE    │  URL 重写、路由跳转
└────────┬────────┘
         ▼
┌─────────────────┐
│   5. PREACCESS  │  限流、限连(limit_req/limit_conn 等)
└────────┬────────┘
         ▼
┌─────────────────┐
│   6. ACCESS     │  访问控制、鉴权、ACL
└────────┬────────┘
         ▼
┌─────────────────┐
│  7. CONTENT     │  生成/转发响应(proxy_pass、静态文件等)
└────────┬────────┘
         ▼
     上游响应返回
         │
         ▼
┌─────────────────┐
│ 8. HEADER_FILTER│  修改响应头(可多次执行)
└────────┬────────┘
         ▼
┌─────────────────┐
│  9. BODY_FILTER │  修改响应体(分块,可多次执行)
└────────┬────────┘
         ▼
┌─────────────────┐
│    10. LOG      │  记录访问日志
└─────────────────┘

三、各阶段详细说明

1. POST_READ

  • 时机:读完 HTTP 请求头之后
  • 典型用途:根据请求头做早期判断、限流前置逻辑
  • 特点:此时请求体通常还未读

2. SERVER_REWRITE

  • 时机:Server 块级别的 rewrite
  • 典型用途:Server 级 URL 重写(比 location rewrite 更早)

3. REWRITE

  • 时机 :Location 匹配后,执行 rewrite 规则
  • 典型用途
    • URL 重写、路径跳转
    • 修改 uriargs
    • APISIX 中很多插件在此阶段运行(如你的 authz-keycloakrewrite 做 introspect)
  • Lua 钩子rewrite_by_lua*

4. PREACCESS

  • 时机:Access 之前
  • 典型用途limit_reqlimit_conn 等限流/限连

5. ACCESS

  • 时机:真正访问上游之前
  • 典型用途
    • 鉴权、IP 黑白名单
    • 决定是否允许继续处理
    • return 403/401 终止请求
  • Lua 钩子access_by_lua*
  • APISIX :多数认证/授权插件的 access 在此执行

6. CONTENT

  • 时机:生成或转发响应内容
  • 典型用途
    • proxy_pass 转发到上游
    • 返回静态文件
    • 自定义响应体
  • Lua 钩子content_by_lua*
  • 特点:这是"干活"阶段,请求会真正发到后端

7. HEADER_FILTER

  • 时机:收到上游响应头、发给客户端之前
  • 典型用途:增删改响应头(CORS、缓存头、安全头等)
  • 注意:可能被多次调用(如 subrequest)

8. BODY_FILTER

  • 时机:响应体发给客户端之前
  • 典型用途:响应体改写、压缩、加密
  • 注意:分块流式处理,可能被多次调用

9. LOG

  • 时机:请求完全结束后
  • 典型用途:访问日志、指标统计、审计
  • 特点 :此时不能再修改响应,也不能 return 影响客户端

四、OpenResty 特有的 Lua 阶段

Lua 指令 对应 Nginx 阶段 说明
set_by_lua* REWRITE(变量求值时) 为 Nginx 变量赋值,禁止 I/O
rewrite_by_lua* REWRITE 可 rewrite、可读 body(需显式 read)
access_by_lua* ACCESS 鉴权、访问控制
content_by_lua* CONTENT 完全由 Lua 生成响应
header_filter_by_lua* HEADER_FILTER 改响应头
body_filter_by_lua* BODY_FILTER 改响应体
log_by_lua* LOG 日志/统计
balancer_by_lua* 选 upstream 时 动态负载均衡
ssl_certificate_by_lua* SSL 握手 动态证书

五、与 APISIX 插件的对应关系

APISIX 插件可注册不同 phase 的钩子,常见映射:

APISIX 插件方法 大致对应阶段 典型场景
rewrite REWRITE URL 重写、早期 token 校验
access ACCESS 鉴权、限流、权限校验
header_filter HEADER_FILTER 改响应头
body_filter BODY_FILTER 改响应体
log LOG 日志上报

执行顺序 :同一插件内 rewriteaccess → ... → log;多个插件按 priority 数值越大越先执行


六、几个实用原则

  1. 越早终止越好 :鉴权失败尽量在 access 或更早返回,避免无效 upstream 调用。
  2. REWRITE vs ACCESS
    • REWRITE:改 URI、早期预处理
    • ACCESS:做"能不能访问"的判断
  3. HEADER/BODY_FILTER 不能阻断请求 :只能改响应,不能 return 错误码给客户端(错误应在更早阶段处理)。
  4. LOG 阶段只做记录:不影响业务响应。
  5. set_by_lua 禁止 I/O:不能发 HTTP、不能查 Redis,只适合纯计算。
相关推荐
章老师说3 天前
NGINX官方谈Lua风险:这其实是两条网关技术路线之争
运维·nginx·负载均衡·lua·openresty
装不满的克莱因瓶1 个月前
基于 OpenResty 扩展开发实现动态服务注册与发现能力
java·开发语言·架构·openresty
wu8587734571 个月前
OpenResty 源站被扫描的排查与防御实战:Cloudflare + DOCKER-USER + Fail2Ban 最全方案解析
docker·容器·openresty
章老师说1 个月前
B站网关事故背后:OpenResty 与 Lua 的稳定性代价
nginx·云原生·负载均衡·lua·openresty
衣舞晨风2 个月前
运行时行为盲区:API7 AI 网关CPU打满故障的AI辅助事后复盘
lua·openresty·apisix·coroutine·cpu-saturation·socket-buffer
rannn_1113 个月前
【Redis|高级篇2】多级缓存|JVM进程缓存、Lua语法、多级缓存实现(OpenResty)、缓存同步(Canal)
java·redis·分布式·后端·缓存·lua·openresty
夜影风3 个月前
Tengine、OpenResty与Nginx三大Web服务中间件对比分析
nginx·openresty·技术架构
難釋懷3 个月前
OpenResty实现Redis查询
数据库·redis·openresty
難釋懷3 个月前
OpenResty封装Redis工具
redis·junit·openresty