本文将从蓝鲸网关的迭代过程和应用 APISIX 后的产品实践角度,为大家呈现基于 APISIX 的网关应用实例。

分享嘉宾朱雷,腾讯 IEG 运维 PaaS 平台技术负责人,将为我们详细讲解蓝鲸(全名“蓝鲸智云”)的背景、诞生背景以及蓝鲸 API 网关的作用。

作为一套孵化于腾讯 IEG(互动娱乐事业群)内部,服务于多业务与各内部平台的研运一体化 PaaS,蓝鲸在 CI、CD 和 CO 三个阶段为公司业务提供全生命周期的服务。然而,这些服务的对象主要来自游戏领域,而游戏业务的特点在于它们是由不同公司所开发,使用的语言、依赖的存储或者整个架构风格可能都是千差万别的。面对这种包含大量异构架构的复杂业务场景,蓝鲸作为一个服务于内部的平台产品,需要做到以下几点:

1. 采用原子化设计,将平台能力抽象、打散,进行微服务化改造,形成一套 PaaS 架构;

2. 使用低代码技术高效开发 SaaS,来使用 PaaS 平台的原子能力;

3. 通过各类 SaaS 来灵活应对不同的服务场景。

考虑到现实中的业务环境与内部业务需求,最终蓝鲸平台的整体架构如下图所示。中间的蓝色部分是 PaaS 层,其中最大的一块是各类原子能力,包括用户管理、统一权限中心、统一配置平台等。上层的橙色部分是 SaaS 层,主要由很多不同角色针对特定需求场景开发的 SaaS 构成。这些 SaaS 在开发过程中,或多或少地都需要通过 API 使用 PaaS 层最核心的各平台原子能力。在这种情况下,就势必需要一个统一的 API 网关。

因此,最初想要打造蓝鲸 API 网关的原因就是为了满足这些需求。将前面的架构图做一些抽象,就会得到一个如下简单的网关画像。蓝鲸是一个比较复杂的平台,它对于统一网关的需求也会比较复杂。除了最基础的作为代理去调用原子平台的 API 之外,还需要提供一些额外的网关能力,如服务发现、统一用户认证、鉴权和限流限速等。

另一方面,随着云原生技术的发展,如今内部很多 SaaS 和原子平台也开始部署在 K8s 集群中。这类场景又向网关提出了新的要求,比如需要通过统一流量网关或 API 网关来将外部的调用请求流量统一管控。

同时,内部还存在一些业务系统,它们本身使用了蓝鲸平台的一些基础架构能力,如容器管理或监控等。这些业务系统也需要一个统一的服务网关来管理所有调用流量。随着外部技术的趋势与内部业务的发展要求,蓝鲸的API网关需要支持的场景逐渐变得多样化。

蓝鲸API网关到目前为止经历了三个阶段的迭代。1.0版本主要让原子平台的调用方(含各SaaS和流程引擎)不再直接对接各个原子平台,而是可以直接调用API网关,通过网关完成协议转换、权限校验等相关功能。当时的架构比较简单,分为服务端和管理端两大块。原子平台需要将自身服务注册到API网关上,首先访问管理端,配置好平台的API资源地址和各自对应的权限等。当SaaS请求某原子平台的API时,数据首先经过前端的NGINX负载均衡器,然后透到网关服务端。服务端读取相关配置后,再将请求通过路由转发功能传给后方的各原子平台,完成整套请求流程。此外,为提升性能,这套架构还引入了Redis处理缓存加速等场景。

然而,1.0版本在内部运行了几年后,随着请求量的增长和场景的复杂化,缺点逐渐显现出来。例如:框架性能不佳,选择的Django框架在高并发场景下表现一般;路由实现性能一般,采用的算法性能较低;DB压力大,路由策略全部存储在MySQL中,规则多时需承载大量检索请求;网络开销大,Redis在多种场景下被高强度使用,导致网络开销太大。

为了解决上述问题,我们在1.0版本的基础上进行了迭代,设计实现了2.0版本。相比前代,2.0版本最大的改动就是使用Go语言重新实现了网关的框架和转发层。Go相比Python,在处理大并发请求的场景下会更有优势。同时还进行了其他优化变动,如在内存中维护了一个更高效的路由实现;在中间层引入了基于内存的缓存,以减少对Redis的依赖;新架构增加了对网关多版本和多环境的生命周期管理;引入扩展插件机制,方便开发者通过插件对网关能力进行扩展。

总体来说,2.0 版本解决了 1.0 版本中遇到的性能问题和大部分痛点。但随着时间的推移,新的问题也开始慢慢浮出水面。

技术选型方面,进入云原生时代后,我们发现网关 2.0 版本在一些方面渐渐无法满足业务需求,主要的问题包括以下几点:隔离性不足、协议支持单一、不支持动态路由规则、缺乏服务发现能力等。结合实际业务场景来说,公司内部有很多业务系统都需要使用这个 API 网关,它们对网关的需求虽然大部分相似,但细微处其实又各有差异。因此,我们有了设计分布式网关的想法。

分布式网关架构的组件主要分为两类:管理端和微网关实例。管理端统一管控着各个微网关,由各网关的管理员对网关进行配置和管理。微网关实例是独立部署的各个网关服务,各自独立承担特定的某一组服务的访问流量,根据管理端的设定进行相关访问控制。所有微网关实例由同一套管理端管控。

在微网关的技术选型方面,我们当时参考了市面上比较流行的多个网关开源产品,从流行度、技术栈、协议支持等各个层面对比后,最终选择了使用 APISIX 作为微网关最重要的后端技术。之所以选择 APISIX 是因为它是基于 NGINX+Lua 实现的,所以整体性能相比 Go 而言是有优势的。同时 APISIX 的扩展性非常好,还支持通过多语言插件去扩展能力,在当时也有非常多的成熟的用户案例。不过,APISIX 在当时对于我们的内部使用场景来说还是存在一些不足之处。比如它的控制面能力有些缺乏,控制面板比较简陋。因此在 APISIX 的基础上我们按照内部需求去实现定制了 APISIX 的控制面。

基于 APISIX 的蓝鲸网关 3.0 迭代则基于 K8s 进行了新的架构设计。

本文介绍了蓝鲸 API网关 30 版本的核心架构和功能。其最核心的部分是使用 K8s 提供的 CRD (Custom Resource Definition) 自定义资源,实现了对网关的整套操作和扩展。网关引入了一整套 K8s 的 CRD 资源定义,包括 BkGatewayStage(网关环境)、BkGatewayService(后端服务)等,通过这些 CRD,用户可以控制每个微网关实例的具体行为。

图中的几个“Operator”是这套架构中最核心的部分。上方是 Plugin Operators 服务,里面包含一系列的插件 Operator。比如负责服务发现的 Operator,会将后端服务注册在服务发现中心的地址写入到 K8s 集群中。中间的核心 Operator 监听着所有和网关相关的 CRD 资源。其中的资源调和器(reconciler),负责将读取到的网关配置转换成 APISIX 微网关实例能理解的格式,从而实现微网关的全套生命周期管理。

目前,这套微网关主要分为两种部署类型:共享网关和专享网关。共享网关是默认类型,平台统一部署,由平台统一生成与管理 API 访问地址;专享网关则是使用方自行部署“微网关”实例,接入平台后变为“专享网关”,需手动管理 API 访问地址,流量直接从“专享网关”流入后端服务。从上图可以看到,管理端统一只有一套,因此它的能力并不提供任何差异化,像多环境管理、权限管理等功能都是所有网关共有。但在它所管理的不同类型的微网关实例中,所支持的特性集就会互有差异。如共享网关实例所支持的特性集是比较基础的,主要包含统一的登录鉴权、限流熔断和多协议支持等;而到了每个业务独立的专享网关实例,就可以拥有一些不一样的个性化能力,因为专享网关和业务同属一个集群,所以它可轻松实现动态路由、自定义服务发现等能力,也可以利用 APISIX 的强拓展性去自定义更多能力。

基于这套架构和模式,蓝鲸 API 网关 3.0 版本在 APISIX 能力的加持下,提供了更加丰富的功能。例如服务发现是微服务架构所需的一个基本能力,在内部,我们主要通过自定义资源 CRD 去实现。一份有效的服务发现 YAML 定义如下图右侧代码所示。将上述 CRD 资源写入 K8s 集群后,就会触发服务发现相关的控制器的相关动作。之后调和器(Reconciler)会捕获到对应的服务发现配置,创建服务发现相关的程序对象。

为了方便开发,我们实现了一个通用的服务发现框架。它提供了统一的开发接口和规范,使用它可以低成本地支持其他类型的服务发现场景。

这个框架通过内置的服务发现接口(包含 Watcher、Lister)读取服务发现中心的相关地址信息,将获取到的地址通过 BkGatewayEndpoints 这个 CRD 资源重新写回到 K8s 集群内。再经由右侧的核心 Operator 进行一些复杂处理后,这些 endpoints 最终被同步到 APISIX 对应的上游中,一次完整的服务发现流程就此完成。

另外,我们还实现了统一认证授权和动态路由功能。在统一认证方面,我们需要支持来自三种不同来源的请求,分别是浏览器、平台和个人用户。我们基于 APISIX 实现了一个认证插件,来实现统一认证。而在动态路由方面,我们主要解决的问题是,当一个 SaaS 调用某原子平台的某个资源时,判断该 SaaS 有没有这个权限。目前统一的资源鉴权也是通过 APISIX 插件实现。

本文主要介绍了蓝鲸 API网关的诞生背景与迭代过程,并分享了选择 APISIX 进行网关产品迭代的过程中的一些业务实践场景。对于非直连集群,首先会生成一个 BCS 集群管理器上游,然后借其和 BCS Agent 进行交互,最后将请求传递给集群的 APIServer。对于直连的集群,流程则类似于前文的统一鉴权插件,插件会定期同步一些与集群相关的基本信息。找到集群信息后生成相关上游,再通过 APISIX 插件去重定义连接逻辑,最后将请求发送到集群 APIServer。

在我们的业务场景中,有一类原子系统在将资源注册到网关时,使用的是比较复杂的客户端证书验证模式。因此,如果某个用户要请求它的资源,就必须提供一份有效的客户端证书。具体实现如上图所示。对于网关管理者,首先要在管理端配置好网关在不同环境中使用的客户端证书。创建完成后,证书会被发布到对应的微网关所在的 K8s 集群中。这个过程会使用一些 CRD 资源和 K8s 官方的 Secret 资源,并由核心的 Operator 服务进行持续地调和处理,比如根据域名寻找对应证书等。有效的客户端证书配置,最终会体现在 APISIX Service 的相关配置中(如上图右上方代码红框处)。

总结来说,本文从蓝鲸 API 网关的诞生背景与迭代过程入手,为大家呈现了一个 API 网关产品的从 0 到 1 的探索过程。也带来了选择 APISIX 进行网关产品迭代的过程中,一些业务实践场景的细节分享。希望对于想要使用 APISIX 进行网关迭代的企业有一些建设性的启发。