场景
我们的程序有时候必须调用第三方接口,有些接口调用频繁,执行速度也很快,几十毫秒就能返回,但每天总有那么几次返回的非常慢,甚至触发了30秒timeout。我们希望这种异常超时发生时,该接口能立即停止执行,返回一个预定义数据,以防止我们自己的客户端卡住或者白屏。
有的第三方接口本身执行比较慢,要500毫秒以上,甚至好几秒,我们希望这种接口能改为异步,执行完毕后再回调通知我们,以防我方的请求变慢。
然而,不幸的是,第三方服务往往不受控,驱动对方修改太过困难。因此也就有了本文的工具:基于Openresty的仅配置服务降级网关。
该网关解决两个问题:
- 接口超时服务降级
- 同步接口转异步
原理
网络结构
工作流程
三种模式
- 透传模式:接口未在toml配置文件中定义时,透传请求给第三方服务接口
- 超时降级:接口在toml中配置为timeout类型时,一旦超出配置的timeout_ms,停止执行,立即返回toml中定义的response
- 同步转异步:接口在toml中配置为callback类型时,网关接收到请求后立即返回toml中定义的response,同时异步向第三方服务接口发送请求,收到第三方服务响应后,回调我方服务
用法
安装网关
yum install -y yum-utils
# CentOS版本 < 9
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
# CentOS版本 >= 9
yum-config-manager --add-repo https://openresty.org/package/centos/openresty2.repo
yum install -y openresty
yum install -y openresty-opm openresty-resty
# opm package,实现超时服务降级和同步转异步
opm get sssxyd/lua-resty-downgrade
systemctl enable openresty
配置Server
vim /usr/local/openresty/nginx/conf/nginx.conf
server {
listen 8280;
server_name _;
root /usr/local/openresty/nginx/html;
charset utf-8;
index index.php index.html index.htm;
access_log /var/log/nginx/access.downgrade.log main;
error_log /var/log/nginx/error.downgrade.log;
autoindex off;
# 静态文件和其他路径请求
location / {
try_files $uri $uri/ /index.html?$query_string;
proxy_pass http://127.0.0.1:8080;
}
# 超时降级/同步转异步
location /thirdpart/ {
access_by_lua_block {
local downgrade = require "resty.downgrade"
downgrade.load_rules("/path/to/your_route_rules.toml")
downgrade.proxy_pass(ngx.var.uri)
}
# 未适配的接口透传
proxy_pass http://127.0.0.1:8080;
}
}
编写规则
vim /path/to/your_route_rules.toml
["/thirdpart/user/getPageData"]
# 当前路由的请求,适配超时服务降级模式
type = "timeout"
# 上游服务地址,支持https
backend_url = "http://127.0.0.1:8080"
# 超时时间,单位毫秒
timeout_ms = 250
# 超时服务降级触发后,返回的HTTP状态码,默认200
#status_code = 200
# 超时服务降级触发后,返回的ContentType,默认JSON
#content_type = "application/json; charset=utf-8"
# 超时服务降级触发后,返回的Body内容
resp_body = '''
{
"code": 100,
"msg": "timeout downgrade",
"result": {
"total": 0,
"data": []
}
}
'''
["/thirdpart/traffic/getTrafficNo"]
# 当前路由的请求,适配同步转异步模式
type = "callback"
# 上游服务地址,支持https
backend_url = "http://127.0.0.1:8080"
# 回调地址,向该接口 Post JSON格式的数据
callback_url = "http://127.0.0.1:8281/handle_callback"
# 当前请求中存储回调凭证的header名称,默认:X-Callback-Credentials,该header可以为空
#callback_credentials_header = "X-Callback-Credentials"
# 同步转异步触发后,立即返回的HTTP状态码,默认200
#status_code = 200
# 同步转异步触发后,立即返回的ContentType,默认JSON
#content_type = "application/json; charset=utf-8"
# 同步转异步触发后,立即返回的Body内容
resp_body = '''
{
"code": 101,
"msg": "callback downgrade",
"result": {
"trafficNo" : ""
}
}
'''
管理服务
# 启动
systemctl start openresty
# 停止
systemctl stop openresty
# 重启
systemctl restart openresty
# 编辑toml后重新加载
openresty -s reload
附录
详情参见: 项目GitHub主页