Skip to content

网关选型

业界有很多流行的 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工作模型

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的功能特性图
Zuul的功能特性图

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

  • 静态响应处理:对于高并发场景下的流量压力,会存在拒绝策略,因此可以直接在服务端返回部分响应,避免转发,减少内部集群的压力。
  • 多区域弹性:这个是对 AWS 的支持,服务可能部署在多个 AWS Region,多区域弹性使得转发的实际服务能够靠近用户所在的地区。

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

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

Zuul1的工作原理图
Zuul1 的工作原理图

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

Zuul2的工作原理图
Zuul2 的工作原理图

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

Kong

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

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 网关的定位,考虑的技术和非技术关注点是什么;
随后才是,基于场景和目标,对比选择更加适合当前业务的微服务网关。