方案目标

.高并发

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

 

 

 

 

 

  1. 请求client根据访问的地址,复用连接对象
  2. 进行写bufio,复用写对象,避免重复创建对象,重新分配内存
  3. 读取,每次对pool的操作,在操作完释放到池子中

 

  1. 根据store配置获取请求api对应的节点,单节点不启用协程;复用dispatchNode池子和wgPool
  2. 分发的多节点复用multiContextPool
  3. 单节点,多节点都复用renderpool、contextPool
  4. 每个分发的节点dispatchNode都有请求,响应、上下文和Runtime
  5. 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 连接保持时间