1. 为什么需要这样的网关?——从业务场景说起
某电商平台在促销活动期间,每秒遭遇数万请求冲击。工程师老王发现:突发流量中有30%是爬虫请求,部分接口被暴力破解,后台日志还混杂着大量过期API的调用记录。这正是现代网关需要解决的三大核心问题——请求过滤(限流防刷)、权限校验(接口保护)、API文档自动化(降低维护成本)。
http {
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
# 共享字典用于限流统计
lua_shared_dict rate_limit 10m;
server {
listen 80;
location / {
# 请求处理阶段声明
access_by_lua_file conf/access_control.lua;
content_by_lua_file conf/service_router.lua;
}
}
}
(注释说明:通过lua_shared_dict建立共享内存区域,access阶段处理鉴权逻辑,content阶段路由到具体服务)
2. 精准的流量手术刀——请求过滤实战
2.1 IP黑白名单控制
-- access_control.lua 片段
local black_ips = {"192.168.1.100", "10.0.0.205"} -- 静态黑名单
local client_ip = ngx.var.remote_addr
if ngx.shared.ip_blacklist:get(client_ip) then
ngx.exit(403)
end
-- 动态封禁(演示10秒封禁)
if is_malicious_request() then
ngx.shared.ip_blacklist:set(client_ip, true, 10)
end
(注释说明:结合内存字典实现动态封禁,避免修改配置重载)
2.2 令牌桶算法限流
-- rate_limit.lua
local limiter = require "resty.limit.req"
local rate = 100 -- 每秒100个请求
local burst = 50 -- 允许突发50个
local lim = limiter.new("rate_limit", rate, burst)
local delay, err = lim:incoming(client_ip, true)
if not delay then
if err == "rejected" then
ngx.exit(503)
end
ngx.log(ngx.ERR, "限流器错误: ", err)
end
(注释说明:采用漏桶算法实现平滑限流,burst参数应对突发流量)
3. 多维权限校验体系——不只是JWT那么简单
3.1 OAuth2.0接入示例
-- auth_validate.lua
local http = require "resty.http"
local cjson = require "cjson"
local function validate_token(token)
local httpc = http.new()
local res, err = httpc:request_uri("https://auth.server/check", {
method = "POST",
body = "token="..token,
headers = {["Content-Type"] = "application/x-www-form-urlencoded"}
})
if not res then return nil, err end
return cjson.decode(res.body)
end
(注释说明:与认证服务解耦,支持分布式鉴权)
3.2 API签名校验
-- signature.lua
local resty_hmac = require "resty.hmac"
local SECRET_KEY = "your_secret_2023"
local params = ngx.req.get_uri_args()
local sign = params.sign
local hmac = resty_hmac:new(SECRET_KEY, resty_hmac.ALGOS.SHA256)
hmac:update(ngx.var.request_uri)
local expect_sign = hmac:final()
if sign ~= expect_sign then
ngx.log(ngx.WARN, "签名校验失败: ", sign)
ngx.exit(401)
end
(注释说明:HMAC-SHA256实现防篡改校验)
4. 文档自动化——让代码自己说话
4.1 注解式文档采集
-- api_doc.lua
local apidoc = {}
function apidoc.collect()
local route_info = {
uri = ngx.var.uri,
method = ngx.var.request_method,
params = ngx.req.get_uri_args(),
desc = "--@desc 用户信息查询接口\n--@param userId string 用户ID"
}
ngx.shared.api_docs:set(ngx.var.uri, cjson.encode(route_info))
end
function apidoc.generate()
local docs = {}
for _, key in pairs(ngx.shared.api_docs:get_keys()) do
docs[#docs+1] = cjson.decode(ngx.shared.api_docs:get(key))
end
return cjson.encode(docs)
end
(注释说明:通过Lua注解自动提取接口元数据)
4.2 Swagger集成输出
location /swagger.json {
content_by_lua_block {
local apidoc = require "api_doc"
ngx.header["Content-Type"] = "application/json"
ngx.say(apidoc.generate())
}
}
(注释说明:自动生成标准Swagger文档,接入现有API管理平台)
5. 关键问题深度分析
5.1 应用场景矩阵
- 金融系统:多重签名+动态限流
- IoT设备:长连接会话管理
- 微服务架构:统一入口治理
5.2 技术选型对比
| 方案 | 性能优势 | 可扩展性 |
|---|---|---|
| OpenResty | 10万+ QPS | Lua模块化 |
| SpringCloud | 完备生态 | Java体系 |
| Envoy | 云原生集成 | C++扩展 |
5.3 性能调优要点
- 共享字典容量预估(1M≈16,000个key)
- LuaJIT FFI优化热点代码
- 定时器实现异步日志上报
5.4 安全防护误区
- 不要依赖单一鉴权方式(JWT+签名双重校验)
- IP黑白名单需配合UA特征识别
- 限流阈值设置必须灰度验证
6. 总结与展望
经过实战检验的OpenResty网关方案,在保持C语言级别性能的同时,通过Lua的灵活性实现了:
- 实时精准的流量清洗
- 多层防御的安全城墙
- 自动维护的文档体系
未来演进方向:
- 机器学习驱动的动态防护策略
- 基于WASM的插件扩展机制
- 无缝对接Service Mesh架构
评论