01#
背景介绍
1.1 出口网关是什么
出口网关(Egress Gateway)是一种部署在云或企业网络中的网络组件,它控制着从内部网络(如企业内网、内部微服务网络)流出到外部网络(如公共互联网或其他外部服务)的流量。一般来说,出口网关是内部服务与外界交互的一个流量出口,实现对外请求的协议转换、流控、监控等通用功能。
相比于传统的入口网关(Ingress Gateway),出口网关侧重于对出站流量进行集中管理与安全控制。例如在爱奇艺对外合作业务中,用户通过入口网关访问爱奇艺内部服务,爱奇艺内部服务再通过出口网关去调用第三方的服务接口,来实现对出站流量的统一管理。
1.2 为什么要做出口网关
1、在爱奇艺会员对外合作业务中,需要访问合作方的 API 接口,随着安全要求的提升,越来越多的合作方对调用方的IP地址实行白名单策略,并且爱奇艺的服务都是在爱奇艺云服务平台进行的部署,业务更新比较频繁,每次更新都会更改IP地址,不可能在每次更新时让第三方进行IP白名单的同步,因此需要实现调用外部接口的统一出口网关。
2、在传统的网络架构下,需为每台应用服务器实例分别申请外网访问权限。实际运维中,这种方法因涉及到服务扩容或迁移操作时的访问权限更新问题,易造成疏漏,从而导致故障,因此需要通过给出口网关配置外网访问权限,内部服务统一通过出口网关访问外网,来规避此问题。
最开始设计出口网关的时候是使用的 Nginx 正向代理来实现此功能,这个方案的问题在于每次新增一个接口都需要调整 Nginx 的路由配置,并且 Nginx 的路由分发只支持静态配置,不能动态增减路由,这就需要在每次配置之后进行 reload,这会增加人工运维的成本,同时 Nginx 正向代理也无法实现流量隔离。
因此,经过调研我们采用 APISIX 作为网关服务的核心,通过 APISIX 插件实现安全防护、流量管控、协议适配等功能,并接入监控系统,同时通过安全插件接入安全团队提供的安全控制系统,并且实现了一个界面化的地址转换服务来实现从 Origin URL 到 APISIX URL 的转换,以便开发人员使用。
1.3 使用出口网关带来的收益是什么
1.3.1 提升研发效率
1、使用网关的开发人员不需要关注出口网关如何实现具体的路由规则,也不需要了解 APISIX 的实现原理,只需要在出口网关管理系统界面中使用地址转换服务,将原本的请求地址转换为网关请求地址,再使用网关请求地址发送请求,即可完成从原始的直接请求方式到网关代理请求方式的转变,全程自助化。
2、通过现有的 APISIX 插件实现安全防护、流量管控、协议适配等功能,避免重复造轮子。
3、APISIX 支持开发人员通过开发自定义组件的方式扩展API网关能力。
1.3.2 降低沟通成本
使用出口网关可以为合作方提供固定的公网IP地址,而无需关注内部服务的具体部署方式,避免大量无效沟通。
1.3.3 提升安全性
在出口网关中接入了安全团队提供的安全控制系统,可以对访问外部服务的请求进行更细粒度的安全审计和控制,防止敏感数据泄漏。
02#
技术设计与实现
2.1 整体架构
出口网关的整体架构如下图所示:
出口网关的控制面主要由管理界面、管理接口与监控系统组成,管理界面提供极简接入与配置界面功能,并且基于 APISIX 的网关配置服务完成配置分发功能,监控系统完成 API 请求监控数据的收集和业务告警功能。
出口网关的数据面主要是由基于 APISIX 的网关核心构成,基于 APISIX 的插件式结构,可以更方便地进行功能扩展,并且支持无状态部署,可在横向上任意扩展,从而提升系统承载能力。同时,对接安全控制系统能有效拦截潜在的不安全请求,提升系统的安全防护能力。
2.1.1 控制面
通过管理界面与管理接口,开发人员可以获取访问出口网关的请求地址,并轻松地完成出口网关的配置。APISIX 通过 admin API 或者 dashboard 可以在毫秒级别内通知到所有的数据面节点,它依赖于 etcd 来作为其配置中心,并且依靠 etcd 集群来确保系统的高可用性。管理接口实际上是对 APISIX admin API 的封装,为了进一步提高系统的易用性,我们并没有直接使用 dashboard 做可视化界面,而是在管理接口的基础上做了一个可视化界面。
配置交互图
管理接口
管理接口的功能如下:
1) 网址转换接口:将外部接口转换为网关地址
2) 网址查询接口:通过网关地址查询外部接口地址
管理界面
在系统一期中,只提供了通过管理接口进行配置的方法,在二期中为了提升易用性,新增了管理界面,管理界面实际是对管理接口的调用与可视化。
2.1.2 数据面
数据面功能的实现主要是基于 APISIX 本身的功能。APISIX 以 Nginx 的网络库为基础,(弃用 Nginx 的路由匹配、静态配置和 C 模块),使用 Lua 和 Nginx 动态控制请求流量,通过插件机制来实现各种流量处理和分发的功能:限流限速、日志记录、安全检测、故障注入等,同时支持用户编写自定义插件来对数据面进行扩充。
API路由
选用 APISIX 做为网关核心主要是因为它的高性能:
APISIX 的路由复杂度是 O (k),K 指 URI 长度,和路由数量无关,例如有一百万条路由,APISIX 路由的时间复杂度都是一样的;
APISIX 的 IP 匹配时间复杂度是 O (1),不会随着大量 IP 判断而导致 CPU
资源跑满,不管有多少IP都是一次命中。
功能组件
出口网关的功能组件是基于 APISIX 插件完成的。主要使用了安全防护、流量管控与协议适配相关功能的插件,并自定义了一个安全插件以接入安全团队提供的安全控制系统。
APISIX插件库:
https://apisix.apache.org/zh/docs/apisix/plugins/batch-requests/
安全防护:
ip-restriction:IP 限制插件,可以通过将 IP 地址列入白名单或黑名单来限制对服务或路由的访问。
ua-restriction:可以通过将指定
User-Agent
列入白名单或黑名单的方式来限制对服务或路由的访问。。referer-restriction:允许用户将
Referer
请求头中的域名列入白名单或黑名单来限制该域名对服务或路由的访问。consumer-restriction:允许用户根据 Route、Service、Consumer 或 Consumer Group 来设置相应的访问限制。
key-auth:用于向 Route 或 Service 添加身份验证密钥(API key)。
jwt-auth:用于将 JWT 身份验证添加到 Service 或 Route 中。
流量管控:
limit-req:使用漏桶算法限制单个客户端对服务的请求速率。
limit-conn:用于限制客户端对单个服务的并发请求数。当客户端对路由的并发请求数达到限制时,可以返回自定义的状态码和响应信息。
limit-count:使用固定时间窗口算法,主要用于限制单个客户端在指定的时间范围内对服务的总请求数,并且会在 HTTP 响应头中返回剩余可以请求的个数。
request-id:通过 APISIX 为每一个请求代理添加 unique ID 用于追踪 API 请求。
协议适配:
grpc-transcode:可以在 HTTP 和 gRPC 请求之间进行转换。
response-rewrite:支持修改上游服务或 APISIX 返回的 Body 和 Header 信息。
2.2 易用性设计
原生的 APISIX admin API 入参比较复杂,配置难度比较高,难以快速上手,我们基于 APISIX admin API 实现了一系列管理接口,简化了入参的复杂性,可以自助化配置。通过配置接口配置只需要请求地址以及相应的校验参数,所用插件都是默认化配置,接入出口网关的开发人员只需要关注于请求地址的转换就可以了。原始 APISIX admin API 配置请求参数如下,可以注意到其配置过程是比较复杂的,不了解 APISIX 插件的开发人员难以了解具体插件配置参数的含义是什么。
配置 Upstream:
配置 Router:
一键化接入界面:
2.3 高可用设计
出口网关作为一个基础组件,高可用性一直是非常重要的部分。
2.3.1 异地多活
出口网关采用多实例、多机房、多地域部署的方式,通过故障自动切换机制,确保服务不中断。同时也可通过自动化弹性应对突发流量。
2.3.2 流量隔离
在实际应用中,由于各业务的流量不一致,某些高流量业务可能会抢占大量资源,从而影响其他应用。出口网关通过令牌方式,将不同业务的流量进行区分和隔离,并针对不同业务设定限流,最大程度保障各业务正常运行。
2.3.3 安全防护
出口网关提供了一个集中点来监控所有出站流量,可通过出口网关更好地实施监控和记录对外请求日志。这对于跟踪数据流向、检测异常行为等非常有帮助。实际做法中,我们将请求日志通过安全团队的安全控制系统进行分析判断请求是否存在异常,以及触发后续流程。
2.3.4 运行监控
出口网关将运行数据实时上报到监控系统,可以从请求成功率、平均响应时间、最大响应时间等多个维度去监控对外的请求情况,发现请求异常,第一时间进行告警。
2.4 可扩展性设计
一个设计良好的基础组件,除了能提供强大的基础能力,还需要有良好的扩展能力。出口网关系统的可扩展性主要体现在 APISIX 本身的可扩展性上,也就是服务节点的无状态部署与 APISIX 插件的可扩展性。
2.4.1 服务节点无状态部署
由于服务节点无状态,可以在内部服务对外请求激增时,简单地通过增加节点数量来扩展系统整体的吞吐量,而不必担心状态同步的问题,这使得出口网关很容易适应流量的变化,保持高适应性,简化运维管理。
由于不依赖本地状态,当节点发生故障时,可以快速替换受影响的节点,无需繁琐的状态迁移,保证了服务的快速恢复和高可用性。此外,无状态节点更容易实现跨云、多区域部署,增强了服务的灾备能力,并且结合K8s可以实现横向弹性自动扩缩容。
2.4.2 APISIX 插件与自定义插件
APISIX 目前已发布了大量插件,并且支持自定义插件,同时支持插件的热加载。
APISIX 插件的实现主要依赖于 OpenResty 对 Nginx 的各个生命周期的钩子函数,允许其在请求生命周期的不同点进行干预或增加额外的功能。并且可以通过自定义插件的方式接入现有的系统,避免二次开发,极大地提升了系统的可扩展性。自定义插件方式:https://apisix.apache.org/zh/docs/apisix/plugin-develop/
此外,相比于 Nginx 在修改配置后,只有reload之后才会生效的做法,APISIX提供了热加载方式。APISIX 热加载主要依赖于 APISIX 的机制和 OpenResty 的特性:由于 APISIX 服务节点是无状态的,这意味着业务处理不依赖于具体的工作进程(worker process),插件的配置都存储在共享内存与外部数据存储中(如 etcd),因此新请求会根据最新的配置来运行插件逻辑,而不依赖于特定的worker进程状态(正在运行的请求还是老配置)。此外,APISIX 的插件系统是模块化的,允许单独加载和卸载 Lua 模块(即插件),当插件本身发生变化,APISIX 可以仅重新加载有变化的插件模块,而无需重载整个系统。
2.5 整体效果
压测性能:单实例 QPS 可以支持 65k+
系统稳定性:99.99%
服务支撑:已接入17个系统,共计600+外部接口
也许你还想看
爱奇艺广告智能算力探索与实践
奇异果TV热修复实践
低延时直播系统在欧洲杯的实践