一、API网关概述
1、什么是API网关
(1)为啥需要API网关
计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。
— David Wheeler
- API网关的观念其实和当前流行的SOA架构和微服务架构模式有关。在传统大型企业比较流行的SOA架构中,有一个企业服务总线(ESB)的概念,再ESB中融合了管理、注册、中介、编排、治理等功能,是一个访问高度频繁、功能高度集中的地方,因此常常也是性能瓶颈所在。而在微服务架构中,伴随着去中心化的理念,几乎没有EBS的的概念,分布式服务架构技术不再依赖于具体的服务中心容器技术( ESB),而是将服务寻址和调用完全分开,这样就不需要通过容器作为服务代理,在运行期实现最高效的直连调用。
- 在微服务架构中,服务的粒度被进一步细分,各个业务服务可以被独立的设计、开发、测试、部署和管理。各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计,这就要求必须使用一种语言和平台无关的服务协议作为各个单元间的通讯方式。而REST API 由于其简单、高效、跨平台、易开发、易测试、易集成,成为了不二选择。此时如果都是采用客户端和服务器直连的话,那么此时系统就会出现大量的冗余代码和功能,维护起来工作量巨大,而且随着服务增多,出错性也大大的增加。因此一个类似综合前置的系统就产生了,这就是 API 网关(API Gateway)。API 网关作为分散在各个业务系统微服务的 API 聚合点和统一接入点,外部请求通过访问这个接入点,即可访问内部所有的 REST API 服务。
(2)API网关定义
网关的角色是作为一个 API 架构,用来保护、增强和控制对于 API 服务的访问。
- API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。因此,隐藏在 API 网关后面的业务系统就可以专注于创建和管理服务,而不用去处理这些策略性的基础设施。
- 通俗的说API网关中就是做一些通用的基础设施功能。类似AOP中的横切关注点概念,把业务系统中涉及的一些通用功能(日志分析、鉴权、路由等)抽取到API网关中统一管理。API 网关不是一个典型的业务系统, 而是一个为了让业务系统更专注与业务服务本身,给API服务提供更多附加能力的一个中间层。
(3)API网关的四大职能
请求接入:作为所有 API 接口服务请求的接入点,管理所有的接入请求;
业务聚合:作为所有后端业务服务的聚合点,所有的业务服务都可以在这里被调用;
中介策略:实现安全、验证、路由、过滤、流控,缓存等策略,进行一些必要的中介处理;
统一管理:提供配置管理工具,对所有 API 服务的调用生命周期和相应的中介策略进行统一管理。
(4)API网关关注点
(1)开发维护简单,节约人力成本和维护成本。
(2)高性能,节约设备成本,提高系统吞吐能力。
(3)高可用(非常重要)
(4)方便灵活地实现安全、验证、过滤、聚合、限流、监控等各种策略。
二、API网关分类
- 如上图所示,面对互联网复杂的业务系统,基本可以将API网关分成两类:流量网关和业务网关。
流量网关:跟具体的后端业务系统和服务完全无关的部分,比如安全策略、全局性流控策略、流量分发策略等。流量网关的功能跟 Web 应用防火墙(WAF)非常类似。WAF一般是基于 Nginx/OpenResty 的 ngx_lua 模块开发的 Web 应用防火墙。
业务网关:针对具体的后端业务系统,或者是服务和业务有一定关联性的部分,并且一般被直接部署在业务服务的前面。业务网关一般部署在流量网关之后,业务系统之前,比流量网关更靠近系统。我们大部分情况下说的 API 网关,狭义上指的是业务网关。并且如果系统的规模不大,我们也会将两者合二为一,使用一个网关来处理所有的工作
三、开源API网关介绍
目前常见的开源网关大致上按照语言分类有如下几类:
Nginx+lua:Open Resty、Kong、Orange、Abtesting gateway 等
Java:Zuul/Zuul2、Spring Cloud Gateway、Kaazing KWG、gravitee、Dromara soul 等
Go:Janus、fagongzi、Grpc-gateway
Dotnet:Ocelot
NodeJS:Express Gateway、Micro Gateway
按照使用数量、成熟度等来划分,主流的有 4 个:
OpenResty
Kong
Zuul/Zuul2
Spring Cloud Gateway
1、Nginx+Lua(Open Resty)
- OpenResty 基于 Nginx,集成了 Lua 语言和 Lua 的各种工具库,可用的第三方模块,这样我们就在 Nginx 既有的高效 HTTP 处理的基础上,同时获得了 Lua 提供的动态扩展能力。官网是这么介绍的:
OpenResty® 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty® 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。
OpenResty® 的目标是让你的 Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。
2、kong
项目地址:
https://konghq.com/
https://github.com/kong/kongKong 基于 OpenResty,是一个云原生、快速、可扩展、分布式的微服务抽象层(Microservice Abstraction Layer),也叫 API 网关(API Gateway),在 Service Mesh 里也叫 API 中间件(API Middleware)。
Kong 开源于 2015 年,核心价值在于高性能和扩展性。从全球 5000 强的组织统计数据来看,Kong 是现在依然在维护的,在生产环境使用最广泛的 API 网关。
Kong 宣称自己是世界上最流行的开源微服务 API 网关(The World’s Most Popular Open Source Microservice API Gateway)。
3、Zuul/Zuul2
项目地址:https://github.com/Netflix/zuul
Zuul 是 Netflix 开源的 API 网关系统,它的主要设计目标是动态路由、监控、弹性和安全。
Zuul 的内部原理可以简单看做是很多不同功能 filter 的集合
-
Zuul 1.x 基于同步 IO,也是 Spring Cloud 全家桶的一部分,可以方便的配合 Spring Boot/Spring Cloud 配置和使用。在 Zuul 1.x 里,filter 的种类和处理流程可以参见下图,最主要的就是 pre、routing、post 这三种过滤器,分别作用于调用业务服务 API 之前的请求处理、直接响应、调用业务服务 API 之后的响应处理。
-
Zuul 2.x 最大的改进就是基于 Netty Server 实现了异步 IO 来接入请求,同时基于 Netty Client 实现了到后端业务服务 API 的请求。这样就可以实现更高的性能、更低的延迟。此外也调整了 filter 类型,将原来的三个核心 filter 显式命名为:Inbound Filter、Endpoint Filter 和 Outbound Filter。
4、Spring Cloud Gateway
项目地址:
https://github.com/spring-cloud/spring-cloud-gateway/
Spring Cloud Gateway 基于 Java 8、Spring 5.0、Spring Boot 2.0、Project Reactor,发展的比 Zuul 2 要早,目前也是 Spring Cloud 全家桶的一部分。
Spring Cloud Gateway 可以看做是一个 Zuul 1.x 的升级版和代替品,比 Zuul 2 更早的使用 Netty 实现异步 IO,从而实现了一个简单、比 Zuul 1.x 更高效的、与 Spring Cloud 紧密配合的 API 网关。
- Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用。
5、四大开源网关框架对比
网关 | 限流 | 鉴权 | 监控 | 易用性 | 可维护性 | 成熟度 |
---|---|---|---|---|---|---|
SGW | 可以通过IP,用户,集群限流,提供了相应的接口进行扩展 | 普通鉴权、auth2.0 | Gateway Metrics Filter | 简单易用 | spring系列可扩展强,易配置 可维护性好 | spring社区成熟,但gateway资源较少 |
Zuul2.x | 可以通过配置文件配置集群限流和单服务器限流亦可通过filter实现限流扩展 | filter中实现 | filter中实现 | 参考资料较少 | 可维护性较差 | 开源不久,资料少 |
Kong | 根据秒,分,时,天,月,年,根据用户进行限流。可在原码的基础上进行开发 | 普通鉴权,Key Auth鉴权,HMAC,auth2.0 | 可上报datadog,记录请求数量,请求数据量,应答数据量,接收于发送的时间间隔,状态码数量,kong内运行时间 | 简单易用,api转发通过管理员接口配置,开发需要lua脚本 | 可维护性较差,将来需要维护大量lua库 | 相对成熟,用户问题汇总,社区,插件开源 |
Open Resty | 需要lua开发 | 需要lua开发 | 需要开发 | 简单易用,但是需要进行的lua开发很多 | 可维护性较差,将来需要维护大量lua脚本 | 很成熟资料很多 |
- 对 Zuul/Zuul2/Spring Cloud Gateway 的一些功能点分析可以参考 Spring Cloud Gateway 作者 Spencer Gibb 的文章:
https://spencergibb.netlify.com/preso/detroit-cf-api-gateway-2017-03/
6、四大开源网关性能对比
(1)实测情况是性能 SCG~Zuul2 << OpenResty ~< Kong << Direct(直连);
(2)Spring Cloud Gateway、Zuul2 的性能差不多,大概是直连的40%;
(3)OpenResty、Kong 差不多,大概是直连的 60-70%;
(4)大并发下,例如模拟 200 并发用户、1000 并发用户时,Zuul2 会有很大概率返回出错。zuul2.x的可用性不好。
- 以上测试用到的模拟服务和网关 demo 代码,大部分可以在这里找到:
7、开源网关的选择
脱离场景谈性能,脱离业务谈架构,都是耍流氓。
- (1)Kong 的性能非常不错,非常适合做流量网关,并且对于 service、route、upstream、consumer、plugins 的抽象,也是自研网关值得借鉴的。对于复杂系统,不建议业务网关用 Kong,或者更明确的说是不建议在 Java 技术栈的系统深度定制 Kong 或 OpenResty,主要是工程性方面的考虑。毕竟维护lua脚本的工作量和成本不低。
- (2)pring Cloud Gateway/Zuul2 对于 Java 技术栈来说比较方便,可以依赖业务系统的一些 common jar。Lua 不方便,不光是语言的问题,更是复用基础设施的问题。另外,对于网关系统来说,性能不是差一个数量级,问题不大,多加 2 台机器就可以搞定。
- (3)目前来看 Zuul2 的坑还是比较多的,因此作为java技术栈,比较建议使用 Spring Cloud Gateway 作为基础骨架。