apisix~OpenResty各阶段的介绍

OpenResty 基于 Nginx 的请求处理模型,在标准 Nginx 阶段上增加了 Lua 钩子。下面按实际执行顺序说明各阶段及其作用。

一、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,只适合纯计算。
posted @ 2026-07-01 16:57  张占岭  阅读(9)  评论(0)    收藏  举报