openresty 通过 lua 在 access 或 balancer 阶段实时决策流量路由,支持灰度、路径、用户等级、健康状态、权重热更新及响应码二次调度。

OpenResty 实现动态流量调度,核心在于用 Lua 在请求处理的各个阶段介入决策,绕过 Nginx 原生静态配置的限制。它不是简单改 upstream,而是让每次请求都能“实时算出”该去哪——比如按灰度标识、地域、API 路径、后端健康状态,甚至历史错误率来动态选节点。
基于请求特征做实时分流
在 location 中用 access_by_lua_block 或 balancer_by_lua_block 读取变量,决定目标分组:
- 识别灰度用户:检查
ngx.var.http_x_env == "canary",则调用balancer.set_current_peer("backend_canary") - 按路径区分:对
/v2/接口走新集群,/v1/走旧集群,用string.match(ngx.var.uri, "^/v2/")判断 - 结合 Cookie 或 Token:解析 JWT 中的
level字段,VIP 用户走高配 upstream,普通用户走默认组
根据后端状态自动调整路由
不依赖被动失败(max_fails),而是主动探测+共享内存标记,实现更灵敏的故障摘除与恢复:
- 用 ngx.timer.every 每 5 秒发起健康探针(如 GET /health?ready=1),记录响应时间与状态码
- 异常节点写入 shared_dict,例如
health:down:10.10.10.1设为 true - 在 balancer_by_lua_block 中遍历 upstream 成员,跳过被标记为 down 的地址
- 恢复策略设为“连续 3 次探针成功”,再从 shared_dict 清除 down 标记
支持运行时权重热更新
避免 reload 配置,把权重存在共享内存中,通过 Admin API 修改:
- 定义
lua_shared_dict upstream_weights 10m;存储各节点权重,如{["10.10.10.1"] = 80, ["10.10.10.2"] = 20} - 在 balancer 阶段读取该字典,做加权随机选择:
math.random() * 100 - 提供内部接口
POST /api/upstream/weight,接收 JSON 更新 shared_dict,无需重启
按响应结果二次调度(如 429/5xx 导流)
利用 $upstream_status 在响应返回后重新决策下一次同类请求的走向:
- 开启
proxy_intercept_errors off,确保原始状态码透传到变量 - 用 map 提前定义映射:
map $upstream_status $target_group { ~^5 $upstream_critical; ~^4 $upstream_slow; default $upstream_normal; } - 在 proxy_pass 中使用
http://$target_group,配合不同 upstream 分组(normal/slow/critical)实现分级承接 - critical 组可指向限流降级服务或告警通道,slow 组可接入缓存兜底或异步队列










