OpenResty入门:OpenResty限流与熔断
一、前言
在高并发场景下,保护后端服务免受流量冲击是至关重要的。OpenResty 提供了强大的限流和熔断能力,可以在网关层面实现对后端服务的保护。本文将介绍如何使用 OpenResty 实现请求限流、连接数限制以及服务熔断。
1、本文主要内容
- 基于
limit_req模块的请求速率限流 - 基于
limit_conn模块的并发连接数限制 - 使用 Lua 实现服务熔断
- 限流与熔断组合配置
- 分布式限流+降级+熔断(基于 Redis + lua-resty-http)
2、本文环境信息
| 工具/环境 | 版本说明 |
|---|---|
| OpenResty | 1.27.1.2 |
| Redis | 7.0+(Docker) |
| 操作系统 | Windows 10/11 或 Linux/macOS |
3、准备工作
1、安装部署 OpenResty
Linux 部署 Openresty|macOS 部署 Openresty|Windows 部署 Openresty|使用 Docker 部署 Openresty
安装后配置把 conf/myconf/*.conf 加入 nginx.conf 中,后续示例中的配置默认都在 conf/myconf 目录下
2、引入 Lua 依赖库
为保证版本一致性,从 GitHub 克隆指定版本:
# 创建目录(Windows 使用 Git Bash)
mkdir -p ~/openresty/lib
cd ~/openresty/lib
# 安装 lua-resty-http(HTTP 客户端)
git clone -b release/0.17.2 https://github.com/ledgetech/lua-resty-http.git
# 安装 lua-resty-redis(Redis 客户端)
git clone -b v0.33 https://github.com/openresty/lua-resty-redis.git
# 复制库文件到统一目录
cp -r ~/openresty/lib/lua-resty-http/lib/resty ~/openresty/lib/
cp -r ~/openresty/lib/lua-resty-redis/lib/resty ~/openresty/lib/
nginx.conf 配置:
在 nginx.conf 中的 http 配置块添加 Lua 包路径:
# Windows
lua_package_path "C:/Users/ken/openresty/lib/?.lua;;";
# macOS
lua_package_path "/Users/ken/openresty/lib/?.lua;;";
# Linux
lua_package_path "/home/ken/openresty/lib/?.lua;;";
📌
cjson使用 OpenResty 内置库,无需额外安装
3、使用 Docker 启动后端服务和 Redis
# 启动后端服务
docker run -d --name backend -p 8000:8080 kentalk/httpserver:latest
# 启动 Redis
docker run -d --name redis -p 6379:6379 redis:latest
测试后端服务:
curl localhost:8000
4、安装 wrk 并测试
# 4个线程、100个并发连接、10秒测试时间
wrk -t4 -c100 -d10s http://localhost:8000
# 测试结果
Running 10s test @ http://localhost:8000
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.19ms 2.23ms 48.85ms 87.22%
Req/Sec 14.14k 1.46k 35.75k 88.78%
564357 requests in 10.10s, 163.62MB read
Requests/sec: 55881.22
Transfer/sec: 16.20MB
📌 测试结果:每秒处理 8552.38 个请求,传输 1.65MB 数据。没有限流熔断机制,所以每个请求都正常返回
5、重要提示
Windows 环境下,由于WSL跟本机的网络隔离特性,默认不能在WSL中访问本机的非80端口,可以在 server_name 中增加本机IP地址,或者也可以更换其他压测工具
- server_name 中增加本机IP地址
listen 8021;
server_name localhost 192.168.1.100;
wrk -t4 -c100 -d10s http://192.168.1.100:8021/
- 其他压测工具
二、请求速率限流(limit_req)
OpenResty 内置的 ngx_http_limit_req_module 模块可以实现基于漏桶算法的请求限流。
1、配置实现
创建 conf/myconf/limit_req_8021.conf:
limit_req_zone $binary_remote_addr zone=req_limit_8021:10m rate=10r/s;
upstream backend_8021 {
server 127.0.0.1:8000;
}
server {
listen 8021;
server_name localhost;
location / {
default_type application/json;
limit_req zone=req_limit_8021 burst=20 nodelay;
limit_req_status 429;
proxy_pass http://backend_8021;
proxy_set_header Host $host;
}
error_page 429 = /rate_limit;
location = /rate_limit {
default_type application/json;
return 429 '{"code": 429, "message": "请求过于频繁,请稍后重试"}';
}
}
配置说明
| 参数 | 说明 |
|---|---|
limit_req_zone |
定义限流区域,使用客户端IP作为key |
zone=req_limit_8021:10m |
区域名称为 req_limit_8021,分配 10MB 内存 |
rate=10r/s |
限制每秒最多 10 个请求 |
burst=20 |
允许突发 20 个请求排队 |
nodelay |
超过限制时立即返回 503,不延迟处理 |
listen 8021 |
监听端口 8021 |
2、测试
重载配置后,使用 wrk 进行压力测试:
nginx -s reload
wrk -t4 -c100 -d10s http://localhost:8021/
预期结果统计:
Running 10s test @ http://localhost:8021/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.21ms 5.58ms 190.80ms 98.57%
Req/Sec 5.20k 798.85 19.38k 97.26%
207484 requests in 10.10s, 47.30MB read
Non-2xx or 3xx responses: 207361
Requests/sec: 20544.32
Transfer/sec: 4.68MB
⚠️
Non-2xx or 3xx responses显示为限流返回的数量(约 207361 个 429/503 响应)
三、并发连接数限制(limit_conn)
ngx_http_limit_conn_module 模块可以限制单个 IP 的并发连接数。
1、配置实现
创建 conf/myconf/limit_conn_8022.conf:
limit_conn_zone $binary_remote_addr zone=conn_limit_8022:10m;
upstream backend_8022 {
server 127.0.0.1:8000;
}
server {
listen 8022;
server_name localhost;
location / {
default_type application/json;
limit_conn conn_limit_8022 10;
limit_conn_status 429;
proxy_pass http://backend_8022;
proxy_set_header Host $host;
}
error_page 429 = /conn_limit;
location = /conn_limit {
default_type application/json;
return 429 '{"code": 429, "message": "并发连接数超限"}';
}
}
配置说明
| 参数 | 说明 |
|---|---|
limit_conn_zone |
定义连接限制区域 |
zone=conn_limit_8022 |
区域名称 |
limit_conn conn_limit_8022 10 |
每个 IP 最多 10 个并发连接 |
listen 8022 |
监听端口 8022 |
2、测试
重载配置后,使用 wrk 进行并发连接测试:
nginx -s reload
wrk -t4 -c50 -d10s http://localhost:8022/
📌
-c50表示 50 个并发连接,正好可以测试限制 10 个连接的效果
预期结果统计:
Running 10s test @ http://localhost:8022/
4 threads and 50 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.40ms 10.98ms 172.29ms 98.34%
Req/Sec 3.02k 467.55 4.12k 72.28%
121764 requests in 10.22s, 27.27MB read
Non-2xx or 3xx responses: 111761
Requests/sec: 11917.53
Transfer/sec: 2.67MB
⚠️
limit_conn统计的是请求数而非真正的 TCP 连接数,只有当请求被处理时才会计数
四、服务熔断(Lua 实现)
OpenResty 可以通过 Lua 脚本实现更灵活的熔断策略,当后端服务异常时自动熔断。
1、配置实现
创建 conf/myconf/circuit_breaker_8023.conf:
lua_shared_dict circuit_breaker_8023 1m;
upstream backend_8023 {
server 127.0.0.1:8000;
}
server {
listen 8023;
server_name localhost;
location / {
default_type application/json;
proxy_pass http://backend_8023;
proxy_set_header Host $host;
}
location = /breaker {
default_type application/json;
access_by_lua_block {
local shared_dict = ngx.shared.circuit_breaker_8023
local circuit_open = shared_dict:get("circuit_open") or false
if circuit_open then
local open_time = shared_dict:get("open_time") or 0
if ngx.now() - open_time < 30 then
ngx.status = 503
ngx.say('{"code": 503, "message": "服务暂时不可用,请稍后重试"}')
ngx.exit(503)
else
shared_dict:set("circuit_open", false)
shared_dict:set("fail_count", 0)
shared_dict:set("total_count", 0)
end
end
}
proxy_pass http://127.0.0.1:8000/error?status=500;
proxy_set_header Host $host;
header_filter_by_lua_block {
local shared_dict = ngx.shared.circuit_breaker_8023
local status = ngx.status
if status >= 500 then
shared_dict:incr("fail_count", 1, 0)
shared_dict:incr("total_count", 1, 0)
local fail_count = shared_dict:get("fail_count") or 0
local total_count = shared_dict:get("total_count") or 0
if total_count > 10 and (fail_count / total_count) > 0.5 then
shared_dict:set("circuit_open", true)
shared_dict:set("open_time", ngx.now())
end
else
shared_dict:incr("total_count", 1, 0)
end
}
}
location = /status {
default_type application/json;
content_by_lua_block {
local circuit_breaker = ngx.shared.circuit_breaker_8023
local keys = circuit_breaker:get_keys()
local result = {}
for _, key in ipairs(keys) do
result[key] = circuit_breaker:get(key)
end
ngx.say(require("cjson").encode(result))
}
}
}
📌 配置说明:
/简单转发到后端服务(不受熔断保护)/breaker触发熔断的测试端点,代理到后端/error?status=500/status查看当前熔断状态
2、测试
重载配置后,使用 wrk 向 /breaker 端点发送请求触发熔断:
nginx -s reload
wrk -t4 -c20 -d180s http://localhost:8023/breaker
检查熔断状态:
# 查看当前熔断状态,可以看压测过程中的数据变化
curl http://localhost:8023/status
预期结果:
{
"total_count": 3651116,
"open_time": 1773773705.707,
"circuit_open": true,
"fail_count": 3651116
}
验证熔断生效:
# 测试 `/breaker` 熔断是否生效,在压测过程中执行
curl -i http://localhost:8023/breaker
预期响应:
HTTP/1.1 503 Service Temporarily Unavailable
Server: openresty/1.27.1.2
Date: Sat, 14 Mar 2026 11:51:01 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
{"code": 503, "message": "服务暂时不可用,请稍后重试"}
💡 30 秒后熔断会自动恢复(半开状态),可以再次测试
3、熔断状态说明
| 状态 | 说明 |
|---|---|
| 关闭 | 正常状态,请求正常转发 |
| 打开 | 熔断状态,直接返回 503 |
| 半开 | 熔断恢复期,允许部分请求通过测试 |
📌 本示例中,当错误率超过 50% 且总请求数超过 10 时触发熔断,熔断持续 30 秒
五、限流与熔断组合配置
将限流和熔断结合使用,实现多层防护。
1、配置实现
创建 conf/myconf/combined_8024.conf:
limit_req_zone $binary_remote_addr zone=req_limit_8024:10m rate=100r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit_8024:10m;
lua_shared_dict circuit_breaker_8024 1m;
upstream backend_8024 {
server 127.0.0.1:8000;
}
server {
listen 8024;
server_name localhost;
location / {
default_type application/json;
limit_req zone=req_limit_8024 burst=50 nodelay;
limit_req_status 429;
limit_conn conn_limit_8024 20;
limit_conn_status 429;
proxy_pass http://backend_8024;
proxy_set_header Host $host;
proxy_connect_timeout 3s;
proxy_read_timeout 5s;
proxy_send_timeout 3s;
error_page 429 = @too_many_requests;
}
location @too_many_requests {
default_type application/json;
return 429 '{"code": 429, "message": "请求过于频繁"}';
}
location = /breaker {
default_type application/json;
access_by_lua_block {
local shared_dict = ngx.shared.circuit_breaker_8024
local circuit_open = shared_dict:get("circuit_open") or false
if circuit_open then
local open_time = shared_dict:get("open_time") or 0
if ngx.now() - open_time < 30 then
ngx.status = 503
ngx.say('{"code": 503, "message": "服务暂时不可用"}')
ngx.exit(503)
else
shared_dict:set("circuit_open", false)
shared_dict:set("fail_count", 0)
shared_dict:set("total_count", 0)
end
end
}
proxy_pass http://127.0.0.1:8000/error?status=500;
proxy_set_header Host $host;
header_filter_by_lua_block {
local shared_dict = ngx.shared.circuit_breaker_8024
local status = ngx.status
if status >= 500 then
shared_dict:incr("fail_count", 1, 0)
shared_dict:incr("total_count", 1, 0)
local fail_count = shared_dict:get("fail_count") or 0
local total_count = shared_dict:get("total_count") or 0
if total_count > 10 and (fail_count / total_count) > 0.5 then
shared_dict:set("circuit_open", true)
shared_dict:set("open_time", ngx.now())
end
else
shared_dict:incr("total_count", 1, 0)
end
}
}
location = /status {
default_type application/json;
content_by_lua_block {
local circuit_breaker = ngx.shared.circuit_breaker_8024
local keys = circuit_breaker:get_keys()
local result = {}
for _, key in ipairs(keys) do
result[key] = circuit_breaker:get(key)
end
ngx.say(require("cjson").encode(result))
}
}
}
📌 配置说明:
/限流转发(rate=100r/s, burst=50, 连接数限制20)/breaker触发熔断的测试端点/status查看熔断状态
2、测试
限流测试:
nginx -s reload
wrk -t4 -c100 -d10s http://localhost:8024/
预期结果统计:
Running 10s test @ http://localhost:8024/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 30.76ms 112.51ms 802.54ms 94.50%
Req/Sec 5.15k 2.09k 19.26k 95.56%
198318 requests in 10.87s, 41.94MB read
Non-2xx or 3xx responses: 197239
Requests/sec: 18237.95
Transfer/sec: 3.86MB
熔断测试:
wrk -t4 -c20 -d30s http://localhost:8024/breaker
curl http://localhost:8024/status
curl -i http://localhost:8024/breaker
六、分布式限流+降级+熔断(Lua + Redis)
在多实例或需要跨 worker 共享状态的场景下,可用 Redis 统一保存限流计数与熔断状态;业务请求经 lua-resty-http 转发到后端,在 Lua 中根据响应码累计成功与失败,用于触发熔断与半开恢复(属于请求路径上的被动统计,与 Nginx upstream 主动健康探测不是同一类机制)。
依赖说明:lua-resty-redis、lua-resty-http 的安装与 lua_package_path 已在 第一节「准备工作」 中配置,本节示例的 *.conf 中不再重复写出。
1、请求处理流程
- 连接 Redis;失败则返回 503(Redis 不可用)。
- 读取
cb:status与cb:open_ttl:若熔断为 open 且cb:open_ttl的值可用(示例中为正数),直接返回 503;若该键已过期或不存在,则把状态置为 half-open 并继续后续步骤。 - 对当前客户端 IP 的限流键执行
INCR,首包设置窗口过期时间;超过「每窗口最大次数」则返回 429。 - 使用
lua-resty-http请求后端(可用?error=500等参数模拟失败)。 - 若响应缺失或
status >= 500:累加失败计数,满足条件则置熔断为 open 并给cb:open_ttl赋值且EXPIRE;向客户端返回 502 及降级 JSON。 - 若成功:累加成功相关计数;half-open 下探测成功则清零并恢复 closed;否则在成功率满足条件时也可恢复关闭状态。
- 将 Redis 连接
set_keepalive归还连接池。
2、响应说明(HTTP 状态与业务含义)
| HTTP | 场景 | 说明 |
|---|---|---|
| 200 等 | 后端正常 | 透传后端状态码与 body |
| 429 | 分布式限流 | 当前时间窗口内该 IP 请求次数超过阈值 |
| 502 | 后端异常或不可达 | 返回 JSON,含 data.fallback 表示降级提示(未熔断但保护性响应) |
| 503 | Redis 不可用 / 熔断打开 | Redis 故障或熔断 open 且仍在 cb:open_ttl 有效期内 |
3、配置实现
创建 conf/myconf/distributed_8025.conf:
server {
listen 8025;
server_name localhost;
default_type application/json;
location / {
content_by_lua_block {
local redis = require("resty.redis")
local http = require("resty.http")
local cjson = require("cjson")
local red = redis:new()
red:set_timeout(2000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.status = 503
ngx.say(cjson.encode({code = 503, message = "Redis服务不可用"}))
return
end
local cb_status_key = "cb:status"
local cb_ttl_key = "cb:open_ttl"
local status = red:get(cb_status_key)
local open_ttl = red:get(cb_ttl_key)
if status == "open" then
if open_ttl and tonumber(open_ttl) > 0 then
ngx.status = 503
ngx.say(cjson.encode({
code = 503,
message = "服务已熔断",
data = {fallback = "系统繁忙,请稍后重试", retry_after = tonumber(open_ttl)}
}))
red:set_keepalive(10000, 100)
return
else
red:set(cb_status_key, "half-open")
status = "half-open"
end
end
local client_ip = ngx.var.remote_addr
local rate_key = "rate_limit:" .. client_ip
local rate_limit = 100
local window = 10
local current, err = red:incr(rate_key)
if not current then
ngx.status = 503
ngx.say(cjson.encode({code = 503, message = "限流服务异常"}))
red:set_keepalive(10000, 100)
return
end
if current == 1 then
red:expire(rate_key, window)
end
if current > rate_limit then
ngx.status = 429
ngx.say(cjson.encode({code = 429, message = "请求过于频繁,请稍后再试"}))
red:set_keepalive(10000, 100)
return
end
local httpc = http.new()
httpc:set_timeout(3000)
local error_status = ngx.var.arg_error
local backend_path = "/"
if error_status then
backend_path = "/error?status=" .. error_status
end
local res, err = httpc:request_uri("http://127.0.0.1:8000", {
method = "GET",
path = backend_path
})
if not res or res.status >= 500 then
local fail_count, err = red:incr("cb:fail_count")
if not fail_count then fail_count = 1 end
local total_count, err = red:incr("cb:total_count")
if not total_count then total_count = 1 end
if fail_count >= 10 or (total_count > 10 and (fail_count / total_count) > 0.5) then
red:set(cb_status_key, "open")
red:set(cb_ttl_key, 30)
red:expire(cb_ttl_key, 30)
end
ngx.status = 502
ngx.say(cjson.encode({
code = 502,
message = "后端服务异常",
data = {fallback = "已触发降级保护"}
}))
else
local health_count, err = red:incr("cb:health_count")
local total_count, err = red:incr("cb:total_count")
if status == "half-open" then
red:set(cb_status_key, "closed")
red:set("cb:fail_count", 0)
red:set("cb:health_count", 0)
red:set("cb:total_count", 0)
red:del(cb_ttl_key)
elseif health_count and total_count and total_count > 10 and (health_count / total_count) > 0.8 then
red:set(cb_status_key, "closed")
red:set("cb:fail_count", 0)
red:set("cb:health_count", 0)
red:set("cb:total_count", 0)
end
ngx.status = res.status
ngx.say(res.body)
end
red:set_keepalive(10000, 100)
}
}
location = /status {
default_type application/json;
content_by_lua_block {
local redis = require("resty.redis")
local cjson = require("cjson")
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say(cjson.encode({status = "redis_error"}))
return
end
-- 与主逻辑保持一致(避免 /status 展示与实际限流参数不一致)
local rate_limit = 100
local window = 10
local client_ip = ngx.var.remote_addr
local rate_key = "rate_limit:" .. client_ip
local rate_count = red:get(rate_key)
local rate_ttl = red:ttl(rate_key)
local current_count = tonumber(rate_count) or 0
local ttl = tonumber(rate_ttl) or -1
local limited = current_count > rate_limit
local remaining = rate_limit - current_count
if remaining < 0 then
remaining = 0
end
local cb_status = red:get("cb:status")
local cb_ttl = red:get("cb:open_ttl")
local fails = red:get("cb:fail_count")
local health = red:get("cb:health_count")
local total = red:get("cb:total_count")
ngx.say(cjson.encode({
rate_limit = {
client_ip = client_ip,
current_count = current_count,
limit = 100,
window = 10,
ttl = ttl,
limited = limited,
remaining = remaining
},
circuit_breaker = {
status = cb_status or "closed",
open_ttl = tonumber(cb_ttl) or 0,
fail_count = tonumber(fails) or 0,
health_count = tonumber(health) or 0,
total_count = tonumber(total) or 0
}
}))
red:set_keepalive(10000, 100)
}
}
location = /reset {
default_type application/json;
content_by_lua_block {
local redis = require("resty.redis")
local cjson = require("cjson")
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.say(cjson.encode({code = 503, message = "Redis连接失败"}))
return
end
local client_ip = ngx.var.remote_addr
local rate_key = "rate_limit:" .. client_ip
red:set("cb:status", "closed")
red:set("cb:fail_count", 0)
red:set("cb:health_count", 0)
red:set("cb:total_count", 0)
red:del("cb:open_ttl")
red:del(rate_key)
ngx.say(cjson.encode({code = 200, message = "限流与熔断状态已重置"}))
red:set_keepalive(10000, 100)
}
}
}
📌 配置说明摘要
/:resty.redis做分布式限流,resty.http转发后端并做成功/失败统计/status:查看当前限流计数、限流状态(limited、remaining)与熔断相关字段/reset:清空本示例中的熔断与当前 IP 限流键(仅供本地与演示;生产必须鉴权、限源或移除)- 限流参数:每个客户端 IP 在 10 秒 时间窗口内最多 100 次请求(固定窗口,窗口长度由首次命中时的
EXPIRE决定)- 熔断触发:
cb:fail_count >= 10,或cb:total_count > 10且失败率> 50%- 熔断恢复:
cb:open_ttl对应键 30 秒 TTL 过期 后进入 half-open;探测成功则恢复 closed(注:本示例返回的open_ttl为配置值,不是实时剩余秒数)
4、限流、降级、熔断测试
因为限流根据IP进行,所以为了避免不必要的麻烦,本章节所有访问都使用实际IP替代localhost
重载配置:
nginx -s reload
限流测试:
# 重置状态
curl http://127.0.0.1:8025/reset
# 终端1:4个线程、10个并发连接,通常会快速超过「10秒100次」阈值
wrk -t4 -c10 -d120s http://127.0.0.1:8025/
# 终端2:查看状态
curl -s http://127.0.0.1:8025/status | jq .
熔断测试:
# 重置状态
curl http://127.0.0.1:8025/reset
# 终端1:错误请求(触发熔断)
wrk -t4 -c20 -d120s http://127.0.0.1:8025/?error=500
# 终端2:查看状态
curl -s http://127.0.0.1:8025/status | jq .
降级验证:
以下 429 / 502 / 503 为不同阶段可能出现的示例响应,不会在同一时刻同时出现:
- 429:触发限流(同一 IP 在 10 秒窗口内超过 100 次)
- 502:后端异常但尚未进入熔断打开阶段
- 503:熔断已打开
# 在进行限流、熔断、降级测试时,新开终端进行验证
curl http://127.0.0.1:8025/
{"code": 429, "message": "请求过于频繁,请稍后再试"}
{"code": 502, "message": "后端服务异常", "data": {"fallback": "已触发降级保护"}}
{"code": 503, "message": "服务已熔断", "data": {"fallback": "系统繁忙,请稍后重试", "retry_after": 25}}
5、生产环境提示
lua-resty-http:高并发下建议为客户端配置连接池或复用连接(如按官方文档使用set_keepalive),避免每次请求新建 TCP 带来的延迟与 ephemeral 端口压力。- lua-resty-redis:对
resty.redis使用set_keepalive(max_idle_timeout, pool_size)并按并发量调大pool_size;连接池不足会导致频繁建连、排队等待与延迟抖动。必要时结合 Redis 端maxclients、网络与超时参数一起压测评估。 /reset:勿对公网开放;可以配合鉴权或由运维限制仅内网管理端访问
七、备忘
1、查看共享内存使用情况
在 Lua 中添加调试接口:
location /status/shared_dict {
default_type application/json;
content_by_lua_block {
local circuit_breaker = ngx.shared.circuit_breaker
local keys = circuit_breaker:get_keys()
local result = {}
for _, key in ipairs(keys) do
result[key] = circuit_breaker:get(key)
end
ngx.say(require("cjson").encode(result))
}
}
⚠️ 生产环境中请移除或保护调试接口,避免信息泄露
2、限流熔断策略总结
| 方案 | 适用场景 | 特点 |
|---|---|---|
| limit_req | 限制请求速率 | 基于漏桶算法,平滑流量 |
| limit_conn | 限制并发连接 | 防止单个客户端占用过多资源 |
| Lua 熔断 | 服务异常保护 | 自动熔断与恢复,保护后端服务 |
| 分布式限流+熔断 | 多节点共享限流计数与熔断状态 | Redis 固定窗口 INCR + 请求路径统计;依赖第一节 Lua 库;降级 JSON;/reset 须在生产保护 |
💡 合理组合使用这些策略,可以有效保护后端服务的稳定性