自建一个简易的OpenAPI网关
网关(API Gateway)是请求流量的唯一入口,可以适配各类渠道和业务,处理各种协议接入、路由与报文转换、同步异步调用等,来管理 API 接口和进行请求流量控制,在微服务架构中,网关尤为重要。
背景
当然,现在已有很多开源软件,如 Kong、 Gravitee、 Zuul。
这些开源网关固然功能齐全,但对于我们业务来说,有点太重了,我们有部分定制化需求,为此我们自建了一个轻量级的 OpenAPI 网关,主要供第三方渠道对接使用。
简介
功能特性
接口鉴权
- 请求 5s 自动过期
- 参数 md5 签名
- 模块粒度的权限控制
接口版本控制
- 支持转发到不同服务
- 支持转发到同一个服务不同接口
事件回调
- 事件订阅
- 最大重试 3 次
- 重试时间采用衰减策略(30s、60s、180s)
系统架构
从第三方请求 API 链路来说,第三方渠道通过 HTTP 协议请求 OpenAPI 网关,网关再将请求转发到对应的内部服务端口,这些端口层通过 gRPC 调用请求到服务层,处理完请求后依次返回。
从事件回调请求链路来说,服务层通过 HTTP 协议发起事件回调请求到 OpenAPI 网关,并立即返回成功。OpenAPI 网关异步完成第三方渠道事件回调请求。
实现
网关配置
由于网关存在内部服务和第三方渠道配置,更为了实现配置的热更新,我们采用了 ETCD 存储配置,存储格式为 JSON。
配置分类
配置分为以下 3 类:
- 第三方 AppId 配置
- 内外 API 映射关系
- 内部服务地址
配置结构
a、第三方 AppId 配置
b、内部服务地址
c、内外 API 映射关系
配置更新
利用 ETCD 的 watch 监听,可以轻易实现配置的热更新。
当然也还是需要主动拉取配置的情况,如重启服务的时候。
API 接口
第三方调用 API 接口的时序,大致如下:
参数格式
为了简化对接流程,我们统一了 API 接口的请求参数格式。请求方式支持 POST 或者 GET。
接口签名
签名采用 md5 加密方式,算法可描述为:
1、将参数 p、m、a、t、v、ak、secret 的值按顺序拼接,得到字符串;
2、md5 第 1 步的字符串并截取前 16 位, 得到新字符串;
3、将第 2 步的字符串转化为小写,即为签名;
PHP 版的请求,如下:
$appId = 'app id'; |
接口版本控制
不同的接口版本,可以转发请求到不同的服务,或同一个服务的不同接口。
事件回调
通过事件回调机制,第三方可以订阅自己关注的事件。
对接接入
渠道接入
只需要配置第三方 AppId 信息,包括 secret、回调地址、模块权限。
即,需要在 ETCD 执行如下操作:
$ etcdctl set /openapi/app/baidu '{ |
服务接入
a、配置内部服务地址
即,需要在 ETCD 执行如下操作:
$ etcdctl set /openapi/backend/form_openapi '{ |
b、配置内外 API 映射关系
同样,需要在 ETCD 执行如下操作:
$ etcdctl set /openapi/api/inquiry/createMedicine.v2 '{ |
c、接入事件回调
接入服务也需要按照第三方接入方式,并申请 AppId。回调业务参数约定为:
Golang 版本的接入,如下:
const ( |
未来规划
- 后台支持配置 AppId
- 事件回调失败请求支持手动重试
- 请求限流