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 重写、路径跳转
- 修改
uri、args - APISIX 中很多插件在此阶段运行(如你的
authz-keycloak的rewrite做 introspect)
- Lua 钩子:
rewrite_by_lua*
4. PREACCESS
- 时机:Access 之前
- 典型用途:
limit_req、limit_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 | 日志上报 |
执行顺序:同一插件内 rewrite → access → … → log;多个插件按 priority 数值越大越先执行。
六、几个实用原则
- 越早终止越好:鉴权失败尽量在
access或更早返回,避免无效 upstream 调用。 - REWRITE vs ACCESS:
- REWRITE:改 URI、早期预处理
- ACCESS:做“能不能访问”的判断
- HEADER/BODY_FILTER 不能阻断请求:只能改响应,不能
return错误码给客户端(错误应在更早阶段处理)。 - LOG 阶段只做记录:不影响业务响应。
set_by_lua禁止 I/O:不能发 HTTP、不能查 Redis,只适合纯计算。
浙公网安备 33010602011771号