Apache APISIX 在 API 和微服务领域的探索

温铭

更新时间 7/22/2022

背景介绍

Apache APISIX 是一个动态、实时、高性能的开源 API 网关,提供负载均衡、动态上游、灰度发布、服务熔断、身份认证、可观测性等丰富的流量管理功能。

作为 API 网关,Apache APISIX 可以帮助企业快速、安全地处理 API 和微服务流量,应用于网关、Kubernetes Ingress 和服务网格等场景。利用 APISIX 既可以处理从客户端到服务端的南北向流量,也可以处理从各个企业微服务之间的东西向流量。

APISIX 在 2019 年 6 月 6 号开源,同年 10 月份捐赠给了 Apache 软件基金会。在之后不到一年的时间内,毕业成为 Apache 顶级项目。

在项目快速发展的背后,APISIX 在技术上进行了哪些探索?为什么会得到越来愈多开发者和企业用户的青睐?在接下来的内容中,将为你讲述更多细节。

APISIX 技术探索之路

摆脱数据库依赖

在 APISIX 项目问世之前,也有非常多的商业 API 网关或开源 API 网关产品,但这些产品大多数都把 API 数据、路由、证书和配置等信息存放在一个关系型数据库中。

存放在关系型数据库的优势其实很明显,可以让用户更加方便地使用 SQL 语句进行灵活查询,方便用户进行备份及后续维护等环节。

但这种情况也会额外带来一个问题。网关作为一个基础中间件,它处理了所有来自客户端的流量,这种情况下对于可用性的要求便会非常高。如果你的 API 网关依赖了一个关系型数据库,也就意味着关系型数据库一旦出现了故障(比如宕机、丢失数据),你的API网关也会因此受到影响。这种情况下,系统的整体可用性就会大打折扣。

所以 APISIX 在设计之初,就从底层架构上避免了类似上述情况的发生。

APISIX 架构

APISIX 的架构主要分成两部分。第一部分叫做数据面,它是真正去处理来自客户端请求的一个组件,去处理用户的真实流量,包括像身份验证、证书卸载、日志分析和可观测性等功能。数据面本身并不会存储任何数据,所以它是一个无状态结构。

第二部分叫做控制面。APISIX 在底层架构上和其它 API 网关的一个很大不同就在于控制面。APISIX 在控制面上并没有使用传统的类似于像 MySQL 去做配置存储,而是选择使用 etcd。这样做的好处主要有以下几点:

  1. 与产品架构的云原生技术体系更统一
  2. 更贴合 API 网关存放的数据类型
  3. 能更好地体现高可用特性
  4. 拥有低于毫秒级别的变化通知

使用 etcd 后,对于数据面而言只需监听 etcd 的变化即可。如果轮询数据库的话,可能需要 5-10 秒才能获取取到最新的配置;但如果监听 etcd 的配置变更,就可以将时间控制在毫秒级别之内,达到实时生效的效果。

所以使用 etcd 而不是关系型数据库,不仅让 APISIX 在底层上更加贴合云原生,也让它在系统高可用的体现上带来了更多优势。

支持多语言插件

API 网关其实和数据库或其他中间件不太一样,虽然都属于基础组件,但对于网关来说,它更多使用场景是进行一些定制化开发和系统集成。

目前 APISIX 官方虽然有非常多的插件,但仍难以涵盖用户的所有使用场景。所以在真实使用场景中,多多少少都会面对业务进行一些定制化的插件开发。通过网关去集成更多的协议或者系统,最终实现在网关层的统一管理。

APISIX 在刚开始只支持使用 Lua 语言进行开发插件。这样做的好处在于,通过原生计算语言的底层优化,可以让开发出来的插件具备非常高的性能。但是它的劣势也非常明显,就是学习 Lua 这门新语言是需要时间和理解成本的。

为此,APISIX 通过两种方式去解决了上述问题。

第一种方式就是通过 Runner Plugin 来支持更多的主流开发语言,比如 Java、Python、Go 等。如果你是一个后端工程师,至少应该会其中一种语言,那么这个时候你就可以非常方便地通过本地 RPC 通信,使用你之前熟悉的计算语言去开发一个 APISIX 插件。

这样做的好处是减少了开发成本,提高了开发效率。当然弊端就是在性能层面有一些损失。那么,有没有一种既能达到 Lua 原生性能,同时又兼顾高级语言的开发效率方案呢?

APISIX 多语言架构

这里就引出了第二种方式,也就是上图左侧部分。WebAssembly 最早是用在前端或浏览器上的一个技术,在服务端它也逐渐展示出来它的优势。

把 WebAssembly 嵌入到了 APISIX 里,用户就可以使用 WebAssembly 去编译成 WebAssembly 的字节码在 APISIX 中运行。最终达到的效果就是利用高效率,开发出了一个既有高性能又使用高级计算语言编写的 APISIX 插件。

所以在目前的 APISIX 版本中,用户可以使用 Lua、Go、Python 和 Wasm 等多种方式,基于 APISIX 编写自定义代码。通过这样的方式,降低了开发者的使用门槛,也为 APISIX 的功能提供了更多的可能性。

插件热加载

APISIX 和 NGINX 相比,有两处非常大的变化:APISIX 支持集群管理和动态加载。

如果大家使用过 NGINX,就知道它的所有配置都会写在 nginx.conf 这个配置文件中。如果想要进行集群控制,就需要一台台去修改它的 nginx.conf 文件。整个过程中没有一个集中化管理的控制平面,每一个 NGINX 都是一个数据面+控制面的混合体。如果此时你有几十台几百台 NGINX,它的管理成本就会特别高。

在上述场景中,修改完每台 NGINX 的 nginx.conf 文件后,都需要重启才能生效。比如进行证书更新或者上游变更,都需要先修改配置文件,然后重启生效。如果你的请求不是特别多,那么这种方法勉强还能接受。但随着越来越多 API 和微服务的调用,如果每次修改都进行重启,这对于客户端的波动其实会非常大。

动态加载列表

上图中列出来了 APISIX 目前在哪些组件中实现了动态加载,从这个列表我们可以看到从上游到证书,甚至插件本身,它的代码都是实时生效的。那么其实在社区里面就会有人问到,他可以理解上游、证书这些是动态的,因为这些会经常变化,但为什么插件的修改也要做成动态的呢?因为插件的修改并不是一个特别频繁的操作,没有必要做成一个极致的动态。

对于 APISIX 的底层设计工程师来说,我们希望它可以做到一个极致的动态。因为极致动态带来了一个非常大的优势就是增加了更多可能性。比如说用户可以在不修改任何插件代码的情况下,对已有代码进行故障排查,这个过程中可能会存在调试插件的修改。那么这种情况下,用户就可以不用重启,继而随时复现问题并记录。这种调试功能的插件配合插件热加载的机制后,就会变得非常灵活,帮助开发者在排查问题的过程中省时省力。

插件动态编排

除了上述提到的插件热加载,APISIX 在插件和插件之间也支持实时的动态编排,动态编排也为插件的运行带来了无限可能。

什么叫插件编排?我们在提出各种各样的需求时,更多是希望可以把一个需求变成一个插件,就像玩乐高一样,通过一个统一的标准(形状契合、交叉等),就可以搭出来无限种可能的造型,这也是乐高的乐趣之一。那么对于 APISIX 的插件来说,每一个插件其实都完成了一个独立的场景需求,那么有没有一种可能,可以让用户像搭乐高一样,把各种插件摆出来让用户自己按照需求进行排列组合呢?

比如 APISIX 现在提供了 100 个插件,那么 APISIX 给用户暴露的功能其实也就只有这 100 个插件所具有的功能,并没有把底层的一些灵活性展露出来。在进行技术中间件开发时,我们不仅需要考虑这个产品现在能做成什么样子,而更应该考虑的是未来用户在上手使用时,能否将这个产品赋予更多可能性。

APISIX 目前有将近 100 个插件,在加入插件编排能力后,你会发现它的可能性不是 100 种,而是100×99×98×97×96x……,也就是接近无限种可能。

举个例子,比如你想对一个用户进行限流限速,当他被限速之后,一般情况下是返回一个错误码。这时你是否可以尝试对接一个日志记录插件,或者是错误上报插件来进行后续的活动记录。下方图片展示了 APISIX 的插件编排模式。

插件编排

这个功能其实隐藏了一个很大的好处,每一个插件的代码都被完整的测试案例覆盖到。也就是说当用户进行插件编排时,可以不用写任何代码。这对于像产品经理、安全工程师以及像运维工程师来说,不需要投入专门的学习成本,只需要拖拽一些插件然后设置一些条件,就可以诞生一个专属自己的 APISIX 新插件,同时这个新插件的代码质量是和开源 APISIX 的官方代码质量一样高。

全流量网关

对于服务端的工程师来说,如果你进行一些和网关相关的开发,基本都会涉及到两个概念。一个是南北向流量,指的是从客户端、浏览器或 IoT 设备等到达服务端的流量,这个流量属于纵向的。另一个就是东西向流量,指的是在企业内部,系统与微服务之间的互相调用,这个流量属于横向的。

在处理纵向和横向的这些流量时,各组件组成也会有所不同。比如在处理南北向流量的组件中,可能会先通过一个 LB,然后再到网关,通过网关之后可能会进入一个业务网关。所以就会有类似于像 NGINX、APISIX、Sping Cloud Gateway 这样的组件。那么在东西向流量中,如果你使用了服务网格,那么可能会用到类似于像 Envoy 这样的组件,这些组件看上去会非常多,但如果仔细观察它们的功能,你会发现这些组件基本上都是一样的,大多都是进行像路由调度、动态上游以及安全身份认证的插件实现等。

所以这种情况下,能否把处理南北向与东西向流量的组件统一起来?理想状态是当一个客户端的请求进到服务端之后,全部由 APISIX 来处理。即不管流量是南北向还是东西向,都是通过控制面去控制所有流量与数据。这在 APISIX 目前的技术探索中,是完全可以实现的。

在实际使用过程中,通过一些现有用户的实践反馈,你会发现这种模式能够大大降低用户自身的运维成本,同时可以降低整体系统的复杂度,从而提升了整个系统之间的响应速度。这样的反馈结果,也让后续 APISIX 的迭代有了更清晰的方向,让 APISIX 在全流量网关层面去尝试更多的功能和角色。

多服务发现组件

网关虽然是基础组件,但它的位置极其重要。它会处理所有来自客户端的请求,处理完成后,对于 API 网关来说还有一个非常重要的职责,就是去和各种各样的系统及开源项目进行集成。

在集成过程中,就会用到一个非常重要的组件——服务发现与注册。因为用户会把各种各样的服务放置到 Eureka、Nacos 这样单独的组件中去完成。对于一些大规模或业务存续较久的 IT 系统来说,多个服务发现组件并存是非常常见的。

这种情况下,其实所有的流量出入口都是网关。你可能需要在A路由上去单独指定一个 Nacos 服务发现,在B路由上指定 Consul 的服务发现等。这对于绝大部分的网关来说,一般都只支持一个服务发现,这时你可能就要部署多套网关,让不同的网关对接不同的服务发现组件。

目前在 APISIX 中不仅支持在数据面的服务发现,也逐步支持在控制面上去对接多个服务注册和发现的组件。这对于一些大规模和业务久远的企业来说,就是一个非常好的解决方案,只部署一个 API 网关,就可以轻松对接多种不同的服务发现和注册组件。

多云与混合云场景探索

对于网关来说,当用户把它部署到生产环境中时,如果是云原生架构,那么多云和混合云必然是一个长期存在的技术场景。对于 APISIX 来说,当它拥有了完善的功能、性能、插件和多服务发现后,就不可避免地去考虑如何让用户在生产环境中更好地去运行起来。

多云和混合云场景其实对 APISIX 带来了更多的挑战,需要考虑更多细节。

  1. 上下游均支持 mTLS

    之前我们觉得支持上游的 mTLS 这个功能的优先级并不高,但一旦处于跨云场景,上游可能就是另外一个云上的服务,或者另外一个 SaaS 服务等。为了提高数据的安全性,就需要进行 mTLS 功能的加持。

  2. 控制面与数据面架构完全分离

    APISIX 在最近一年中被爆出来几个安全漏洞,这些安全漏洞的来源很多是因为 APISIX 的控制面与数据面是混合部署在一起的。可以理解为 APISIX 服务启动完成之后,它的控制面与数据面在同一个服务里。此时如果一个黑客通过安全漏洞入侵了某个数据面,那么也就意味着他有机会能够入侵到控制面,从而控制所有的数据面,造成非常大的影响。

    在 APISIX 后续的架构设计中,我们在考虑把数据面与控制面完全分离。采用不同的端口与服务,将其部署在完全不同的服务器上,从而避免出现上述安全隐患。

  3. 加强安全管理

    网关一般会存储一些比较敏感的数据,比如有些用户可能就会直接把 SSL 证书存储在网关上,或者把连接 etcd 的密钥信息存在网关上。这种情况下一旦 etcd 被侵入了或者数据面被攻破,就有可能造成比较严重的数据泄密。

    因此就需要考虑在存储一些关键信息时,去支持使用 Vault 这样专门存密钥的组件来进行敏感信息的保护。这样做不仅可以让 APISIX 自身更加安全,也能够让用户使用 APISIX 时更加合规。

  4. 集成更多云上标准

    在多云情况下我们需要去考虑,APISIX 在类似阿里云、腾讯云及 AWS 等云服务商中使用时,如何与他们更好地融合在一起来使用?我们的初衷是希望用户不用配置任何东西就能够在各个云平台上顺利运行起来。

    这个过程的实现,并不说让用户再进行自定义插件配置,而是直接让 APISIX 去集成各个云上的标准、 API 或其他服务,提前帮用户做好适配,保证后续用户的直接上手体验感。

前行之路的支持者

纵观 APISIX 的发展历程,其实在技术层面做了非常多的创新。不管是从一开始的代码搭建,还是目前仍然保持的快速迭代,越来越多的社区贡献者们携手并进,将 APISIX 逐渐搭建成了完整且功能日渐丰富的API网关。

一个开源产品的迭代与进步,必然少不了贡献者与使用者的功劳。

在 APISIX 刚捐赠给 Apache 软件基金会时,它还并不是一个特别成熟的项目,那时的 APISIX 只有 20 个贡献者。如今的迅速发展,也让 APISIX 在全球范围内收获众多使用者、贡献者和企业用户。比如 WPS、新浪微博、爱奇艺等国内大厂,这些都是每天承载几百亿次 API 调用的企业用户。 在海外也有像 NASA、欧盟数字工厂、瑞士电信等非常多的一些用户在使用。

APISIX 企业用户

拿 WPS 这种云办公软件来说,不管你在手机、浏览器还是终端设备上进行多人协同办公时,几十甚至几百个人可以同时去编辑一份文档,同时你可以实时查看到其他人进行的修改。这个功能实现的背后,就是通过 API 的各种调用来实现的。

国内这些大厂企业用户的使用场景中,多是处理上百亿 API 调用和峰值 QPS 超百万的规模。这种使用规模下,也让 APISIX 真正在大规模场景中得到历练与收获真实场景反馈。得益于这些企业用户的场景使用,APISIX 作为开源产品才得以更成熟快速发展。

当然除了将 APISIX 应用到企业业务中来,很多使用者在使用 APISIX 的过程中,也会把他们的一些经验或者代码功能迭代等反馈给社区,实现了双方互利共赢的趋势。这也说明使用者们不仅觉得 APISIX 是一个好的产品,更是一个值得去参与其中的开源项目。先赢得开发者们的喜欢,才有机会去变成一个真正有价值的开源项目。

贡献者们用体验和反馈打造了非常多的产品功能,使用者们利用这些功能又可以给企业带来价值。这个才是真正开源的精髓所在,而不是一味只去追求各种表面数据而带来的数字繁荣。

APISIX 3.0 前瞻

至此我们聊了非常多关于 APISIX 在过去及现在进行的探索。从时间线来看,可以把 APISIX 的发展历程分为几个阶段。

APISIX 1.0 阶段,是在打造这个产品的框架,将底层架构打理好并呈现一些 API 网关的基本功能。来到 2.0 阶段,则是在初始版本上进行了更细致的探索,让底层更加灵活,让架构更加丰满。

对于一个成熟的开源项目来说,它成熟的标志并不是说功能有多强大,而是在产品使用上,为用户和开发者带来更好的使用体验。

在目前阶段中,APISIX 都是在技术上进行了非常多的探索与创新,但并未考虑到使用者背后的感受,比如文档质量参差不齐、教学视频少之又少等现状。这就让很多用户在刚接触 APISIX 时,存在茫然与不知所措。不知道怎么使用,不知道如何将某些功能应用到什么场景,不知道 APISIX 这些强大的功能背后能给企业带来怎样的独特价值。

所以在接下来的 APISIX 3.0 阶段中,会尝试解决类似的问题,重构掉目前很多对于开发者体验不友好的地方。比如重新去设计 API,去掉对于 etcd 的一些特殊返回值的依赖;重构官方使用文档,让文字性这种最直接的表达方式对开发者更加友好。在功能层面,也会进行控制面与数据面分离,让 APISIX 本身变得更加安全;支持更多的 4 层协议,支持更多的 RPC 协议,让用户可以非常方便地去实现南北东西向的全流量网关。

APISIX 3.0 功能一览

这些待实现功能加在一起,你会发现 APISIX 3.0 阶段将会变得比之前版本更加安全可靠与易用。功能强大的同时,仍不忘使用体验。我们希望未来的 APISIX,是可以处理全球所有 API 和微服务的请求,最终达到一个非常好的使用价值,助力企业在 API 和微服务流量的处理上更加便利。

预计在 2022 年年底,APISIX 将会发布全新的 3.0 版本,希望大家也可以持续关注 APISIX 新版本的各种动向,踊跃参与 Apache APISIX 项目共建。