4

编写本文并非打算总结开发开源网关的最佳实践,仅仅是谈谈自己的一些观点。

基石

如果有人问我,开发开源网关最重要的是什么,我会毫不犹豫地提到两点:

  1. 要有一套一致的设计语言。
  2. 要有持续的人力投入

设计语言

由于现在开源项目内卷化,要想推出一个新的开源网关,已经必须要有整套的控制面(CP) + Dashboard + 数据面(DP)。只是开源其中几个组件而非整体产品,就意味着给竞对留下空间来占领你的市场。你可以开源出一个入门版的实现,但是至少不能没有。

既然我们要开源出一个整体产品,就需要有一个可以打通各个层次的设计语言。比如 APISIX 用 jsonschema,kong 有自己的 schema,envoy 有 grpc。一个设计语言需要满足两个目标:

  1. 能编写配置,可以在多种平台下面使用,支持在配置中增加标记。
  2. 支持丰富的检验规则,如必需的字段、有效值的范围、根据某个字段来决定对其他字段的检验规则等等。

有了这个设计语言之后,我们可以避免在不同的组件间重复代码,并提供一致的体验。比如 Dashboard 的表单字段和数据面的配置项,都可以由该设计语言编写的配置中生成。这时候,用户就可以根据表单字段名称找到数据面上具体的配置,方便学习和调试。

人力投入

虽然网关的门槛不高,但是竞争激烈,而且投入周期长。所以需要有足够多的人力,持续地在这上面工作。

开源网关是一个红海。在我脑海里,能立刻报上名字的开源网关个数,在十个以上。其中大部分背后都有一个团队在运作。甚至还有几家网关卷不过别人,抱团合作的情况。(没错,我说的就是 Envoy gateway)

开源网关的开发是一个马拉松。APISIX 在 2019 年 6 月开源,在 2020 年内也主要是在 OpenResty 圈子里面流行。直到 2021 年,APISIX 才算是国内 API 网关界的一个标杆。到了 2021 年冬,APISIX 终于能够有个爆发性的增长。此时距离开源已经过去了两年多。总结就是,第一年让大家知道你;第二年陆续有人使用你;到第三年才会有使用量的飞跃。开源网关的开发没有速胜论。

有人会问,既然做的是开源网关,我们可以依靠众多的贡献者来降低人力成本吗?以 APISIX 为例,作为一个专注于发展社区、吸纳更多贡献者的项目,APISIX 有着 350 多位贡献者。所有非 API7 员工加起来的代码量,占当前 APISIX 的 40%。换句话说,有 60% 是由 API7 的员工实现的。我统计过许多开源项目的贡献者分布,大部分项目都是由核心开发者贡献了半数以上的代码。这意味着,实际上我们还是需要有持之以恒地投入核心开发者来推动网关的开发工作。

定位

既然开源网关竞争激烈,那么我们就需要有一个清晰的定位,先占住一块利基市场,才能活下来。一个良好的定位,对内可以说服金主持续的投入,对外可以说服用户坚定地选择。一个网关,可以主打丰富的功能、可以主打低部署成本、可以主打强劲的性能,但是不能是一个样样皆通、样样稀松的平庸的网关。力要往一处使,需要在开始时找到自己发力的方向,饶有毅力地往上钻,才能打出自己的一片天。

不过,无论网关的定位如何,都需要解决两个问题:

  1. 让用户用起来
  2. 让用户用下去

让用户用起来

抛开一些非技术的手段不谈,要想让用户上手你的网关,首先要有清晰容易的部署方式,其次要有简明扼要的文档引导。最好一条命令就能让整个网关跑起来,并在读完 10 分钟以内的文档后完成 Hello World 示例的配置。

让用户用下去

在把人吸引过来之后,我们就要考虑留住人了。通常来讲,用户对网关的应用是比较小心谨慎的,往往需要经历很长时间才能做到充分地信任。所以我们需要保证这个网关是非常稳定的,不会给他们带来意外的“惊喜”。

这个稳定分两类。一个是功能上的稳定,用户使用了不会担心出线上事故。从网关的开发上讲,我们需要有一套周全的自动化测试流程来保障这一点。另一个是配置上的稳定,用户不用担心升级了某个版本之后,配置就出问题了。在这一点上,我们可以借鉴 Envoy 和 k8s 的做法,通过把配置字段给版本化,在提供了清晰的配置升级路径的同时,也保证了旧有配置的稳定性。

迭代

由于本文的主题是关于开源网关的,那么这里的迭代,主要指如何把开源贡献者的力量引入到网关的迭代中来。

如前所述,网关的主要开发,还是要由核心开发者完成。核心开发者需要把骨架搭起来,把流程跑通,开源贡献者才能去往里面填充新的功能。

所谓的“搭建骨架”,有三个含义:

  1. 需要把文档、测试、CI 给打通,贡献者只需要照着现有的代码加上自己的就行,不需要琢磨如何增加新的机制。
  2. 需要把拓展点给放置好,贡献者只需要围绕这个拓展点编程,比如新增一个插件或配置 provider,只需参考现有的就行。
  3. 做新功能时,只实现一个 MVP 的功能。比如调用鉴权服务时,第一版的实现只会发送客户端请求的头。如果用户想要一个增加额外自定义头的功能,可以邀请他一起来开发。当然这么做也要控制好度,避免被人吐槽只是做了个门面。

有道是,“海纳百川,有容乃大”。当维护者的,心里总是希望能合并更多人贡献的代码。但有时他们却不会这么做。通常这会是出于两个理由:

  1. 对贡献者缺乏信任
  2. 怕增加维护成本

要想降低合并新功能所需的信任和维护成本,我们可以创建一个 contri 目录,专门放置更外围的代码。默认情况下,不会启用(甚至打包) contri 下面的代码。同时我们会在文档中声明,contri 下面的代码的安全性不由该项目维护者负责。我们还可以弄一份文档,记录 contri 里面每个插件的实际 owner 是谁。总而言之,我们需要强调 contri 里面的代码是有另外的 owner 的,一旦有问题,可以撇清责任。这么一来,对信任和维护成本的要求就可以降低了。

文档

最后,但不是最不重要的,开源网关要有良好的文档。为什么我会把文档的事情独立来说呢?因为无论你选择哪种技术栈来开发网关,都需要思考同样的文档问题。

开源网关的文档,通常可以分为以下各部分:

  1. Concept。包括入门指南、网关的架构、本文档中涉及的术语等,是给初学者看的。
  2. Cookbook。包括面向各种场景下网关的配置方式,是给已经入门的用户看的。
  3. Reference。包括网关的各种配置字段说明,是给用户查找的。
  4. Ops Guide。包括如何做高可用、如何升级、如何调试,是给运维看的。
  5. Dev Guide。包含如何拓展该网关,如何贡献代码。是给开发者看的。

核心开发者需要把文档的架构给搭起来,方便贡献者来完善它。

由于本文是用中文写的,读者都是中文用户,所以自然而然地会有一个问题 —— 我们是否要提供中文文档?

从我个人实践角度看,提供中文文档,与其说是降低门槛,不如说是传达一种我们重视本地化的态度。如果人力允许,还是要做的,但是我们需要有一个自动化的方式来做。毕竟现在 AI 这么发达,如果不用上它实在算不上一个程序员。Databend 曾经分享过自己的自动化流程:https://xuanwo.io/reports/202... (虽然我看它的文档里面有翻译的内容仍然只是小部分)。


spacewander
5.6k 声望1.5k 粉丝

make building blocks that people can understand and use easily, and people will work together to solve the very largest problems.


引用和评论

0 条评论