本文是 2021 年 12 月 26 日,第三十五届 - 前端早早聊【前端搞 Node.js】专场,来自涂鸦的大前端基础建设团队 —— 龙野的分享。感谢 AI 的发展,借助 GPT 的能力,最近我们终于可以非常高效地将各位讲师的精彩分享文本化后,分享给大家。(完整版含演示请看录播视频和 PPT):https://www.zaozao.run/video/c35
正文如下
大家好,我是涂鸦智能的龙野,目前在团队中主要负责前端网关和 Node 这个语言基础方向的一些建设。今天我分享的主题是《如何用 Node 建设企业级应用网关》。
背景
前端网关的背景可以追溯到几年前,当微服务刚刚出现时,我们在 Java 技术体系中有一张架构图。
整个微服务大致是这样的,外部请求从用户端进来后,先经过负载均衡器,再到达一个外部网关,最后被转发到集群内部的各种服务,不论是 Java 还是其他语言的服务。在集群内部可能存在许多各式各样的服务,服务之间的上下层划分并不是非常明确。因此,外部网关到内部服务之间的边界并不是特别清晰。
当某个服务出现问题时,外部网关路由层代理到内部时,我们需要定位或排查问题时可能会比较复杂。而且,如果这个服务出现问题后,需要迅速发布一个修复版本,由于各个公司的发布系统稳定性依赖于整个流程,可能需要较长的时间。
所以,我们希望能够在外部网关到内部服务之间架设一个业务方向的网关,这就是现在 BFF 网关产生的背景。类似于现在的前置 BFF 网关,它是挂在外部网关之后,并且挂在内部服务集群的业务之前的一中间的代理层。这层代理层也就是聚合服务,即 BFF 网关最初产生的背景,它的目的是想要将不同的上游服务的数据聚合后反馈给用户。
在这个基础服务层中,我们可以扩展其功能。
-
当上游的某个服务出现问题时,可以在 BFF 网关中进行兜底操作,避免请求到达出现问题的服务。
-
BFF 网关可以统计针对某个业务方向的流量,同时对恶意请求进行过滤。
-
引入了 BFF 网关,用于在常用的服务中进行封装和泛化,以处理不同的调用方法。业务方只需在网关中配置一个通用的接口,并使用通用的配置方式,即可请求不同的服务。
-
BFF 网关还具有聚合接口数据的功能,以减少前端浏览器发起的请求数量,提高页面的流畅度。
-
BFF 网关可以通过配置实现多接口的聚合,使前端浏览器只需通过一次请求即可获得多个接口的数据。
-
我们封装了一些公共能力,通过网关插件,允许对业务有更深了解的人直接编写网关插件以解决业务问题,降低业务开发接入的复杂度。
-
除此之外,使用这种网关还有一些其他附加价值。 a. 例如,具有数据伪造功能,网关可以通过配置直接提供假数据,在云端或服务端暂时无法提供实际数据环境下进行联调; b. 自带服务发现能力,用户只需知道网关地址,即可请求网关,无需关心网关内部的路由和数据来源; c. 缓存能力,如果在特殊场景下这些服务出现了问题,我们可以返回上一次正常响应的页面。
今天要讲的内容一共分为以下几个部分,后面我们将按照这个顺序进行简要讲解。
网关基本架构
我们简单聊一下 BFF 网关的架构。
作为内部用户,对于网关,我希望它能实现请求到达网关后代理到特定的服务,从而完成我要做的事情。但是业务的网关需求较为复杂,不仅仅是简单的代理。如果只是简单的代理,那么直接部署一个 Nginx 不就好了吗?
我们希望做的是最初的设想,即具备动态化配置 Nginx 的能力。默认情况下,Nginx 的规则是写在 Nginx 的 conf 文件中的,但是如果要动态修改这些规则怎么办呢?了解过 Nginx 配置的同学应该知道,修改完后执行 reload 命令就可以使新的配置生效。
那么作为一个开发人员而不是运维人员,我应该如何修改这个 Nginx 配置呢?社区中有很多类似的实践,其中一个典型的例子就是将 Nginx 的配置写入到 Consul 中,Consul 会以文件的形式将配置下发到 Nginx 特定的目录。这样,Nginx 可以通过执行 Nginx 的 reload 命令来加载新的配置。我们最初设计网关时的想法实际上就是这样的。我们希望用户能够自定义他们的规则,并将这些规则下发到线上的各种环境中。因此,我们先开发了一个网关后台系统,内部用户可以在后台系统中配置代理规则。然后,我们对这些规则进行了抽象,引入了项目的概念,项目下面包含了路由,这些路由函数的逻辑由我们自己来定义。用户可以将这些配置和数据写入线上特定环境的持久化存储中。