作者:楼磊磊
来源:金融级分布式架构公众号
本文将介绍 SOFAGW 互通网关,首先切入在跨站点通信时碰到的核心痛点,引入 SOFAGW 互通网关的解决方案,会重点说明如何解决在安全、互通、接入成本、高效等几方面问题,介绍 SOFAGW 网关的内部实现架构,展示 SOFAGW 网关达成的业务成果。
业务痛点
随着业务发展越来越多元化,部分业务域相对比较独立,或因其业务属性,会建立成独立的站点(租户),比如:国际业务和蚂蚁保等。这些站点之间网络是隔离的,但实际业务上会存在一些通信的需求,所以我们碰到的核心问题是:网络互相隔离的多个站点之间怎么做高效可信的通信?对此我们有两种针对站点间互通的解决思路:
思路1:为每个业务创建跨域 VIP
为每个业务创建跨域 VIP,站点的业务通过 VIP 来做通信。这种方式,运维管理员要在两个网络间开很多 VIP,加访问白名单,最终网络拓扑会变成如下;将面临网络口子多、运维成本高、业务接入成本高、安全阈值低等问题。
这个方案有以下几个问题:
- 很多服务需要开 VIP 口子,服务多了之后,VIP 难以维护;
- VIP 的 ACL 控制很弱,只能基于 IP 端口或 IP 段控制,不能按业务应用或服务来做控制;
- 安全管控能力很弱,对请求不可审计;
- 业务适配改造工作量大,技术栈不统一,存在多种 RPC 框架。
思路2:实现一个高效可信的互通网关,来承接站点之间的通信代理
这就是我们采用的多站点互相通信的解决方案,下面详细介绍我们的互通方案和重点解决的问题。
解决方案:SOFAGW 互通网关
鉴于上面提到的问题,我们研发了 SOFAGW 互通网关,致力于实现一个简单高效、安全可信的跨域 RPC/消息 互通网关。
如上面的整体架构图所示,我们的解决方案是各站点部署一套 SOFAGW 网关,把站点间的通信都收敛到 SOFAGW 上,由 SOFAGW 来保证安全通信,而在研发体验上,业务方同学按照本地服务做开发,不用为跨域通信做特殊处理,做到无缝接入。
RPC 互通过程:
- 在 SOFAGW 网关上,申请接入需要互通的 RPC 服务。接入后,消费方 SOFAGW 网关会把这个 RPC 服务发布到本站点注册中心上,服务方 SOFAGW 网关会从注册中心订阅这个 RPC 服务提供方地址。
- 消费方应用通过注册中心订阅到目标服务是本站点的 SOFAGW,把请求发送到本站点的 SOFAGW。
- 本站点的 SOFAGW 根据 API 配置信息,把请求转发到对端站点的 SOFAGW。
- 对端站点的 SOFAGW 根据注册中心订阅到的地址,把请求发送给真实的服务提供方。
- 完成跨展达 RPC 通信。
消息互通过程:
消息的互通和 RPC 互通非常类似,差别主要在于需要通过消息中心来收发消息。
- 在 SOFAGW 网关上,申请需要接入互通的消息服务。
- 客户端把消息投递到本站点的消息中心,消息中心把消息封装成 RPC 请求发送到本站点 SOFAGW。
- 对端站点的 SOFAGW 把请求发送到消息中心,消息中心再把消息投递到真实的消费方。
- 完成跨站点消息投递。
SOFAGW 互通网关重点解决以下几个痛点:
1、安全通信
首先我们要解决网络不可达问题。从图里可以看到:每个站点都部署了 SOFAGW 网关,网关之间可以用专线或 VIP 之类的产品打通,这样站点间把流量就收敛到了 SOFAGW 网关,避免到处开网络通道口子,便于安全管理。
网络安全
为了保证 SOFAGW 网关之间的通信安全可信,我们开启了 mTLS 双向认证,既能对数据做加密,也能确认对方的身份可信,从而确保通信安全。
数据安全
一个站点(租户)会给其他多个站点提供服务,这些暴露的服务首先要确保租户级别的水平权限隔离,也就是说,A 站点暴露给 B 站点的服务,不能被 C 站点的应用调用到。如何做到这点?
- SOFAGW 网关会给不同站点提供不同的访问域名(这些域名都会解析到 SOFAGW 的 VIP 上)。
- SOFAGW 之间通过 mTLS 双向认证通过后,可以确认请求的域名( host )可信,也就是 C 站点的应用无法用B 站点的域名与 A 站点的 SOFAGW 网关建立 TLS 连接。
- SOFAGW 会通过请求头里的 host + path 路由做路由转发,C 站点的请求无法匹配上提供给 B 站点的域名,也就无法访问到提供给 B 站点的服务。
除了要确保租户级别的水平权限控制,SOFAGW 还具备应用级别的 ACL 权限控制,如果一个 API 服务只暴露给某特定应用,那其他的应用是无法访问这个 API 服务的。
另外,站点间的通信数据不是任意的,目前在业务 API 接入过程中,我们会有严格的数据安全审计流程。
2、统一技术栈,跨域 RPC/消息 互通
不同的业务方会使用不同 RPC 框架,如 SOFARPC、HSF、Dubbo,底层用的通信协议和序列化协议也不一样,很难直接通信,如果做协议转化适配又会有很大的成本。在性能、扩展性和新特性支持等方面,老的各种协议难以满足发展需求,也很难在原有协议的基础上扩展以支持新的功能。为了更好的支持业务发展,对齐各 RPC 框架通用能力,需要设计一种新的通用的协议,从协议层解决以上问题。
所以,阿里巴巴及蚂蚁集团共同制定了 Triple 协议,让内部使用的编程框架都支持 Triple 协议,这样大家互通时就会很顺畅。
Triple 协议是什么?
Triple 协议本身,是基于 gRPC-over-HTTP2 扩展的 RPC 协议,与现有的其他 RPC 协议比较, 有以下优势:
- 多种 RPC 模式 ( P2P/ Reactive Streams/ Bidirectional / Pub-Sub )
- 基于 protobuf 提供统一的服务定义以及 API 治理
- 更好的性能 ( Protobuf / Protostuff / Back Pressure )
- 原生跨语言支持 ( C++/ Dart/ Go/ Java/ Python/ Ruby/ C# / OC / JS / PHP ),原生兼容 gRPC 客户端
- 易于升级和修改协议
- 兼容现有的 RPC 框架,易于协议升级和互通 ( gRPC / SOFA-RPC / HSF / Dubbo ...)
- 对网关型应用友好,原生支持 gRPC-over-HTTP2
- 支持移动设备原生调用
Triple 遵循 gRPC-over-HTTP2 协议规范,使用 CUSTOM-METADATA 扩展元数据。对于已经存在的 grpc- 开头的 Header 保持不变,保证与原生 gRPC 客户端/服务端互通,对于协议中不存在需要新扩展的 Header,将以 tri- 开头。另外,即将发布的 Dubbo 3.0 也是以 gRPC 为基础,Triple 能和 Dubbo 3.0 保持良好兼容。
举例,当前我们约定的 Triple 协议头:
3、无缝接入
为了让业务方无缝接入,SOFAGW 网关和注册中心专门做了联动,具体原理从上面的整体架构图可以看到:
- 在调用端,SOFAGW 网关把目标服务发布到了注册中心,调用端可以通过注册中心订阅到 SOFAGW 网关地址,请求直接打到 SOFAGW 网关上。
- 在服务端,SOFAGW 网关从注册中心订阅了服务端地址,SOFAGW 收到请求后,直接把请求路由到目标服务端。
通过这套逻辑,研发同学在研发时就按照本地服务做开发,不用为跨域通信做特殊处理。
在研发框架和协议适配上,我们还做了以下优化:
- 针对双边使用了不同的 RPC 框架,大家统一使用 Triple 协议,我们对 SOFARPC、HSF 等框架升级支持了 Triple 协议,用户升级框架后支持发布订阅 Triple 服务,和原先使用 RPC 几乎一样,用很低的成本接入使用 RPC 互通服务。
- 同时 SOFAGW 网关也支持 Bolt 协议,对于双方都使用 SOFARPC 框架场景,业务方不需要改造就可以实现无缝对接,完成跨站点 RPC 通信。
从前面的架构上可以看到,站点间通信需要过两次网关,整体链路变长,对问题定位排查都增加了额外的成本。为此,我们做了全链路 tracer 打通、压测流量识别和打通,借助服务治理平台,业务方可以快速定位到问题出现在哪个环节。
4、 高效、高性能
站点间通信经过两次网关,通信耗时肯定会有所上升,再加上网关自身的开销和网络时延等,整体效率是下降的。为了减小这些额外开销,我们从几个方面做了优化:
- 支持灵活的路由能力,缩短网络跳转距离
- 网关和系统参数调优,提升性能
多种路由能力
对于一个站点(租户),它可能有多个机房多地部署,而且不同机房的服务不一定对等,我们需要提供灵活的路由配置能力,来降低整个链路上的网络开销。为此,SOFAGW 网关提供了多种路由能力:
- 指定目标机房路由
- 按地理位置就近路由
- 蚂蚁的单元化路由
- 自定义配置路由
这些路由能力除了能提升通信效率,还有其他的作用,比如按百分比引流、灰度引流验证等,这里不再详述。
网关和系统参数调优
从架构看,整体链路好像没什么问题,实际压测发现,有很多细节点影响性能,导致并发量上不去。最典型的问题,是发现请求和响应的传输耗时高,进一步通过 netstat 命令发现 send-q 一直较高,说明网络有积压,对此我们做了几个针对性的优化:
- 调小单连接的 max_pedding_request,创建更多连接:目的是减小单连接的并发压力,同时,创建多个连接也可以让负载更加均衡。
- 修改 tcp_rmem 和 tcp_wmem 内核参数:这两个是 TCP 读写缓冲区 size 参数,会影响 TCP 滑动窗口的大小,一般这两个参数不需要设置,但我们发现部分机器上设置的参数有问题,默认的 buffer size 太小,导致 TCP 滑动窗口 size 上不去,影响了数据收发速率。
- 修改内核参数 tcp_autocorking:设置为 1 的情况下,操作系统会尽量将较小的包汇聚成一个较大的包再发送。这里我们将双方网关的 tcp_autocorking 设置为 0。
- 增加 DNS 异步解析缓存,避免 DNS 解析导致的高耗时。
- 网关连接的 idle 超时时间调整,避免频繁建连带来的额外耗时。
SOFAGW 内部架构实现
下图是 SOFAGW 网关的内部架构,介绍下内部各组件的作用:
控制面:
- configer 和 provider:网关配置管理器,网关的配置完整定义了各组件的行为,比如 API 配置来源、listener 的端口和协议、handler 的插件等。配置来源可以是管控端、Istio、本地文件,根据配置里的 API 定义,会从注册中心订阅服务端地址构建起 upstream 的集群信息。
数据面:
- listener:网关的监听器,也是网关接收请求的入口,根据定义的端口、协议、连接参数等信息处理对应的请求。
- handler:网关的核心处理器,这里可以自定义很多插件,来选择是否启用一些能力,比如限流、路由等。
- dialer:网关的转发处理器,这一层比较简单,就是把请求转发给后端服务器。
总结和价值
SOFAFW网关和常见API网关差异
目前常见的 API 网关有 Spring Cloud Gateway,Zuul2,OpenResty,Kong 等,它们的核心能力是把内部的 API 服务代理给外部业务调用,并且提供统一拦截所有请求,实现安全、限流、审计等能力。
从前文可以看到,SOAFGW 互通网关和这些网关的主要差别在定位场景上,我们的核心目标是实现安全可靠的 RPC/消息 互通服务,主要特点有:
- 实现跨域 RPC/消息 互通
- 安全可信
- 业务无缝接入
- 高性能和高稳定性
SOFAGW 网关和Service Mesh的联系
Service Mesh 也就是服务网格,通过 Sidecar 做服务之间的通信代理,从这个定位上能看出,SOFAGW 网关在数据面上做的是同样的事情,都是服务通信代理,是Service Mesh的自然延伸。
事实上,SOFAGW 网关就是基于蚂蚁开源的 Service Mesh 框架 MOSN 实现,所以 SOFAGW 网关可以复用 MOSN 的很多能力和插件,比如最新发布“Service Mesh 双十一后的探索和思考(上)”中提到的链路加密、自适应限流、精细化引流等能力。
最终我们呈现给用户的是业务方可以无感实现跨域 RPC/消息 互通,并保证通信链路的安全可靠稳定。原先业务方通过其他方式实现站点间通信需要 2-7 天,接入 SOFAGW 网关后,平均接入时间降到半天内,大大提升了研发效能。
上线不到一年,SOFAGW 网关已承载几百个服务,日常峰值流量在几十万 QPS,转发成功率为 99.99992%,服务了不少核心业务,成功支撑了 2020 年的双 11 和双 12 大促。