方案目标
.高并发
Golang在网络层有很高的并发性,网关比较高的性能取决于网络层的高效性。目前id转换接口,同时测试golang和java服务,在2核cpu环境性能区别golang是在java的2倍左右。等golang开发完,可以一起设计方案来比对压测数据。
.高稳定性
上线前多测试,目前我自己使用的golang网关经过多个项目线上的验证,只需要按照我们需求进行修改。
.和现有网关分流上线
这要求golang网关和java网关实现相同功能和业务逻辑。
和微服务都采用http,相同的转发规则,相同的错误码返回格式,相同的业务逻辑处理,在权限验证业务需要查询redis。golang网关需要覆盖完成现有java网关全部功能,不然达不到效果一致性。
目前java网关的功能和架构
规则转发,限流,熔断;动态配置,日志记录。权限redis查询,验证。
功能 | 实现 |
规则转发 | 按Apollo配置进行动态更新转发规则。规则算法:按url前缀进行匹配服务器名称进行转发 |
Ereuka服务发现 | 通过Ereuka进行服务发现和注册。动态更新转发服务器缓存。 |
限流,熔断 | 支持api级和服务级限流 |
网关业务逻辑 | 对token进行了redis查询和算法验证。 |
Golang网关功能与实现
功能:规则转发
实现:目前规则有一个字段和两个字段作为匹配前缀,golang实现采用map[前缀][服务名称]的缓存结构体,查找O(1)时间复杂度。
功能:支持Apollo 动态更新配置
实现:定时3分钟去查询一次Apollo配置,对本地进行更新。采用mapA用于前端访问,mapB用于在定时器中和Apollo查询的数据进行比较。只有出现比较不一致,才会用mapB去更新mapA,才会需要锁lock,平时没有锁操作。
功能:支持Ereuka动态更新服务
实现:采用map[服务名称]ip列表 结构,在路由规则中找到服务名称后,找到ip列表,采用随机算法选择一个ip作为转发的服务器。三次转发调用出现error,异步通知更新map[服务名称]ip列表结构体缓存。定时3分钟去查询一次Ereuka数据。算法复杂度O(1)
功能:日志记录每次请求的输入和输出
实现:目前采用本地文件方式存储,一条日子记录输入参数和头部信息,输出结果,一次访问两条记录。记录格式如下:
[2020-10-20 14:33:21.975] [dbug] [CompanyRouterByOpenId.go:87] msg="FindCompanyThirdIdByOpenId request" ctxID=901943137508 body="{\"openId\":\"0042da5269634dd6bbb2c732a11a937d\",\"toClientId\":\"300412f27c3311e9ac7c8cec4b6d151c\"}"
功能:对于错误码的返回
实现:对于调用微服务接口还有网关内部逻辑出现的错误。一律采用应用层错误码返回,http的状态码一律是200,返回格式是:
"{"code":50001,"message":"内部错误",
"data":nill,
"timestamp":1602675150647,
"isSuccess":false}"
功能:白名单,黑名单功能
实现:采用配置列表方式设置白和黑名单,包括一个配置项表示是白名单还是黑名单,名单不长,直接采用数组存储,查找效率常数项。
功能:限流,熔断
实现:目前在调研golang写的比较好的第三方组件实现。
功能:支持长链接
实现:目前java系统有一个长连接是nginx直接访问的微服务,没有经过java网关。可以第二版实现。
Golang网关技术方案选项
Manba框架原型:
技术点:
Fasthttp、ETCD
Features
- 流量控制(Server或API级别) 熔断(Server或API级别) 负载均衡 服务发现 插件机制 路由(分流,复制流量) API 聚合 API 参数校验 API 访问控制(黑白名单) API 默认返回值 API 定制返回值 API 结果Cache JWT Authorization API Metric导入Prometheus API 失败重试 后端server的健康检查 开放管理API(GRPC、Restful) 支持websocket 支持在线迁移数据
改造:
dispatch
- 请求client根据访问的地址,复用连接对象
- 进行写bufio,复用写对象,避免重复创建对象,重新分配内存
- 读取,每次对pool的操作,在操作完释放到池子中
- 根据store配置获取请求api对应的节点,单节点不启用协程;复用dispatchNode池子和wgPool
- 分发的多节点复用multiContextPool
- 单节点,多节点都复用renderpool、contextPool
- 每个分发的节点dispatchNode都有请求,响应、上下文和Runtime
- task监听chan,处理转发和流量拷贝等操作
启动参数配置说明:
LimitCountConn 1000 单点连接数
LimitTimeoutRead 5s 连接读超时
LimitTimeoutWrite 5s 连接写超时
LimitBufferRead 2048 每个buffer对象读字节数
LimitBufferWrite 1024 每个buffer对象读字节数
LimitCountDispatchWorker 64 多节点复用时dispatch创建的worker数
LimitCountCopyWorker 4 流量复用时请求对象创建的worker数
LimitBytesBody 10M 最大的操作内容字节数
LimitDurationConnIdle 30s连接等待空闲时间(超过这个时间会被回收)
LimitDurationConnKeepalive 60s 连接保持时间