在上一课时我们介绍了网关的基本原理,并动手实现了一个 Go 简易网关。那本课时我们就接着来探讨微服务网关的选型。

业界有很多流行的 API 网关,比如开源的就有 Nginx、Netflix Zuul、Kong 等。Kong 有商业版,与此类似的商业版网关还有 GoKu API Gateway 和 Tyk 等。

GoKu API Gateway 是由国内公司Eolinker 使用 Go 语言研发的,拥有社区版和商业版,包含 API Gateway 和 Dashboard 两部分。其中,社区版本包含大量基础功能,可以满足中型企业和产品的使用;商业版本则包含更多扩展,比较适合大型软件和大型组织使用。

Tyk 由国外的 TykTechnologies 公司研发,也是基于 Go 语言的。但Tyk 一切均导向收费版本,免费版本第一次申请仅有一年的使用授权。

看到这里,估计你,包括很多开发人员,肯定是希望基于开源组件来构建自己的网关,而不是去使用付费的网关服务。所以,下面我们就来介绍Nginx、Zuul 和 Kong 这几种常用的开源API 网关组件的相关特性。

Nginx

Nginx 是于 2000 年初开发的,初衷是为解决服务端经典的C10K 问题,即在给定的内存大小内处理 10000 个以上的同时连接,在这个过程中,其他 Web 服务器的每个连接都需要占用内存,因此它们会耗尽物理内存,并在成千上万的用户同时访问一个站点时响应慢或者崩溃。Nginx 采用的是多进程事件模型、异步非阻塞的方式处理请求,因此可以同时处理成千上万个请求,并优雅地扩展到更多用户。

在工作方式上,Nginx 有单工作进程和多工作进程两种模式。默认情况下,Nginx 启动后,在后台以多工作进程模式运行,Nginx 的后台进程由一个 Master 进程和多个 Worker 进程组成。当然,我们也可以通过对 Nginx 进行配置,取消 Master 进程的运行,使得 Nginx 以单进程方式运行。

Nginx 工作模型图

Nginx 工作模型图如上图所示,Master 进程协调 Worker 进程,是通过进程间通信实现交互。下面我们具体介绍 Nginx 中的Master 进程和 Worker 进程:

Master进程, 管理进程,用来协调 Worker 进程。Master 接收到信号,向 Worker 进程发送对应的信号。除此之外,Master 进程还会监控 Worker 进程的运行状态,当 Worker 进程发生异常退出时,就会重启新的 Worker 进程。

Worker 进程, 从字面就可以知道,这是实际工作的进程。Worker 进程主要处理基本的网络事件,多个 Worker 进程之间相互独立对等,客户端请求到来时,这些进程同等竞争来自客户端的请求,最终由其中一个 Worker 进程来处理这个请求。

当 Nginx 标准模块和配置不能灵活地适应系统要求时,就可以考虑使用 Lua 扩展和定制 Nginx 服务。Nginx 中可以嵌入 Lua 脚本,通过将定制的 Lua 脚本部署到 Nginx,使得 Nginx 类似于一个 Web 容器。我们在开发的时候一般使用 OpenResty 来搭建开发环境,因为 OpenResty 集成了优秀的 Lua 库、第三方模块,可以方便地搭建能够处理超高并发、扩展性极高的 Web 服务。这样开发者就只需要安装 OpenResty,不需要了解 Nginx 核心和写复杂的 C/C++ 模块就可以使用 Lua 语言进行 Web 应用开发。

Nginx 中有多个模块,这些模块根据其功能可以分为如下几种:

事件模块。有 Ngx_Events_Module、Ngx_Event_Core_Module 和 Ngx_Epoll_Module 等模块。事件模块提供单独的事件处理机制的框架,并提供了对各个具体事件的处理。至于使用何种 Nginx 事件处理模块,则由具体的 OS 和编译选项决定。

解析模块。接收客户端请求,并响应内容,比如返回静态页面的模块 Ngx_Http_Static_Module,将对应的静态文件作为响应返回给客户端。

输出过滤模块。对输出的内容进行处理,Nginx 中可以对响应进行修改。例如,常见的有增加 Header 或者移除 Header,这些头部可能是服务端内部的标识,因此需要我们使用输出过滤模块对响应头进行处理。

Upstream 模块。一种特殊的解析模块,反向代理在此模块实现,Nginx 收到请求后根据配置文件,将请求转发到对应的实际后端服务器上,并返回响应给客户端。

Upstream 模块提供的反向代理功能,使得 Nginx 具备了数据转发功能,为 Nginx 增强横向处理能力,摆脱了服务端单机处理的限制,从而使 Nginx 具备了软件级别的整合、拆分功能。使用 Nginx 的反向代理和均衡可实现负载均衡及高可用,除此之外还需要我们解决自注册和网关本身的扩展性问题。

Netflix Zuul

Zuul 是一款由 Netflix 开源的、流行的微服务网关组件。Java 中的 Spring Cloud 框架整合了 Zuul ,因此 Zuul 与 Consul、Ribbon、Hystrix 和 Eureka 等组件可以无缝集成,非常方便。对于使用 Spring Cloud 生态构建微服务体系的公司来说,选择 Zuul 作为微服务网关是个不错的选择。

Zuul 的核心是一系列的过滤器,这些过滤器可以完成以下功能:

Zuul 的功能特性图

上图中的大部分功能,你应该已经都很熟悉了,这里我们就着重讲解下静态响应处理和多区域弹性这两个功能。

静态响应处理:对于高并发场景下的流量压力,会存在拒绝策略,因此可以直接在服务端返回部分响应,避免转发,减少内部集群的压力。

多区域弹性:这个是对 AWS 的支持,服务可能部署在多个 AWS Region,多区域弹性使得转发的实际服务能够靠近用户所在的地区。

上面描述的一些特性是 Nginx 不具备的,这是因为Zuul设计之初的目标就不仅仅是作为类似于 Nginx 的反向代理,而是意在解决云环境下的种种问题。Zuul 目前有两个大的版本:Zuul1 和 Zuul2。

Zuul1 的设计比较简单,本质上就是一个同步 Servlet,如图所示。Spring Cloud 中集成的 Zuul 版本, 采用的是 Tomcat 容器,使用的是传统的 Servlet IO 处理模型。Zuul 的多线程阻塞模型,即一个线程处理一次连接请求,这种方式在内部延迟严重、设备故障较多情况下会引起存活的连接增多和线程增加的情况发生。

Zuul1 的工作原理图

Netflix 发布的 Zuul2 有重大的更新,采用异步非阻塞的方式处理请求,每个 CPU 核对应一个线程,用来处理所有的请求和响应。请求和响应的生命周期是通过事件和回调来处理的,这种方式减少了线程数量,因此开销较小。

Zuul2 的工作原理图

非阻塞模式可以接受的连接数大大增加,这种模式下,请求到达则进入处理队列,这个队列的容量可以设得很大。在请求超时之前,队列中的请求都会被依次处理。又由于数据被存储在同一个 CPU 里,Zuul2可以复用 CPU 级别的缓存,这种方式较Zuul1线程切换来说轻量级很多,消耗会较小。

Kong

Kong 由 Mashape 公司开源,是一款高性能高可用的微服务网关,是基于 OpenResty(Nginx + Lua模块)编写的高可用服务网关,由于 Kong 是基于 Nginx 的,因此可以很轻松地水平扩展 Kong 服务器。通过负载均衡把请求转发给各个服务端实例,来应对大批量的网络请求。

Kong 的基本运行图

Kong 的基本运行情况如上图所示,客户端请求到达 Kong 网关之后,经过一系列插件的处理之后,才会将请求转发给指定的后端服务。Kong 主要包括 Kong Server、Apache Cassandra/PostgreSQL 和 Kong Dashboard三个组件。

Kong Server:基于Nginx的服务器,用来接收 API 请求。

Apache Cassandra/PostgreSQL:用来存储操作数据。

KongDashboard:官方提供的 Kong 图形化管理工具,如果不使用图形化界面的话,也可以直接使用 Restful 方式管理 Admin API。

这三部分组成了完整的 Kong 网关。Kong 本身也是基于 Nginx 的,所以在性能和稳定性上都没有问题。Kong 网关具有以下的特性:

可扩展性。通过简单添加更多的服务器,可以轻松进行横向扩展,这意味着平台可以在一个较低负载的情况下处理任何请求。

模块化。这是 Kong 的一大特性,可以通过添加新的插件进行扩展,且插件可定制开发,可以通过 Kong Dashboard 或者 RESTful Admin API 进行配置。

可在任何基础架构上运行。可以在云环境或内部网络环境中部署 Kong,对云原生环境有着天然地支持。

基于 Kong 插件机制,使用 Lua 脚本开发,可以便捷地进行功能定制,这些插件(可能是 0 个或者 N 个)在 API 请求响应循环的生命周期中被执行。Kong 中提供的基础插件包括:HTTP 基本认证、Key Authentication、CORS(Cross-Origin Resource Sharing,跨域资源共享)、OAuth2.0 认证、文件日志、网关限流、请求的路由转发和服务监控等。我们会在下面的课时重点介绍这其中的几款插件。

网关对比

在前面我们已经简要介绍了 Nginx、Zuul 和 Kong 这三种 API 网关组件的功能和特性,为便于你更好地理解,在这里我专门梳理出了这三种 API 网关的对比表格,如下所示:

总体来说,Zuul 复杂度较低,上手简单,可以自定义开发,但是高并发场景下的性能相对较差;Nginx 性能经受得住考验,配合 Lua 可以引入各种插件,但是功能性相对较弱,需要开发者自身去完善很多功能;Kong 基于 Nginx、OpenResty 和 Lua,如果对性能要求高,需要对外开放的场景,建议考虑使用 Kong。

小结

微服务网关的选型,是这两年来很多转型微服务开发的工程师和中间件工程师关心的一个问题,因此本课时我们就专门介绍了几种业界流行的微服务网关,并做了简要对比。

其实当考虑要选用哪一款微服务网关组件时,我们首先需要清晰网关的引入能够给目前的业务现状带来什么,以及 API 网关的定位,考虑的技术和非技术关注点是什么;随后才是,基于场景和目标,对比选择更加适合当前业务的微服务网关。

最后,你觉得微服务网关的选型需要考虑哪些因素,你使用的是哪一款微服务网关?欢迎你在留言区和我分享。

-– ### 精选评论 ##### **1609: > traefik算网关吗?老师 ######     讲师回复: >     一款反向代理组件,有些场景下也会用作网关。 ##### *敏: > 大佬,少了apisix ######     讲师回复: >     对,还有其他的一些网关,文章只选取了其中语言代表性的几个组件做了对比。 ##### **升: > soul网关 ######     讲师回复: >     看来你是soul的忠实支持者