开源openapi&微服务应用gateway的对比

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 最近需要搭建一个openapi管理平台,准确一点,具备可视化管理界面的gateway网关,研究了快一个月,主要看了一下产品apisix,kong,fizzgate,VX-API-Gateway ,apinto。。。确没有一款是我的需求【接口调用统计,黑白名单,lb,接口聚合】,希望对大家有帮助

网关的选型失败

当时,市面上存在两种类型的解决方案:

  • 中间层的解决方案。中间层方案一般提供裸异步服务、其他插件以及功能根据需求自定义,部分中间层的服务经过改造后也具备网关的部分功能。
  • 网关的解决方案。网关方案一般围绕着微服务全家桶提供,或者自成一派,提供通用型的功能(如路由功能)。当然,部分网关经过自定义改造也能加入中间层的业务功能。

    截屏2019-12-16下午8.08.55.png

我们的业务发展变化非常快。如果市面上已有的网关方案能满足需求,我们又有能力进行二次开发,我们非常乐意使用。

当时,Eolinker 是我们的 API 自动测试的供应商,提供了对应的管理型网关,但语言是 Go。而我们团队的技术栈主要以 Java 为主,运维的部署方案也一直围绕着 Java,这意味我们的选型就偏窄,因此不得不放弃这一想法。

在之前,我们也选择过 Kong 网关,但是引入一个新的复杂技术栈是一件成本不低的事情,比如,Lua 的招聘与二次开发是难以避免的痛。

另外,Gravitee、Zuul、Vert.x 都是不同小规模团队使用过的网关。谈及最多的特性是:

  • 支持熔断、流量控制和过载保护
  • 支持特别高的并发
  • 秒杀

然而,对业务来说,熔断、流量控制和过载保护应该是最后考虑的措施。而且,对一个成长中的团队来说,服务的过载崩溃是需要经历较长时间的业务沉淀。

另外,秒杀业务的流量更多是维持一个普通水平,其偶尔的高并发也是在我们团队处理能力范围之内。换句话说,选型时,更多的是需要结合实际,而不是考虑类似阿里巴巴的流量,我只需考虑中等水平以上并且具备集群扩展性的方式即可。

但是,Vert.x 社区缺乏支持以及入门成本高的问题一直存在,而团队甚至找不到更多合适的同事来维护代码。

以上网关的选型失败让我们意识到,市面没有完全符合我们公司的情况的“瑞士军刀”。

需要的设计

为解决这些问题,我们需要让网关与中间层模糊界限,抹去网关和中间层隔阂,让网关支持中间层动态编码,尽可能少的发布部署。为实现这个目的,只需要用一个简洁的网关模型并同时利用 low-code 特性尽可能地去覆盖中间层的功能即可。

img

从原点出发的需求

在复盘当初这个选择时,我需要再强调下从原点出发的需求:

  • Java 技术栈,支持 Spring 全家桶;
  • 方便易用,零培训也能编排;
  • 动态路由能力,随时随地能够开启新 API;
  • 高性能且集群可横向扩展;
  • 强热服务编排能力,支持前后端编码,随时随地更新 API;
  • 线上编码逻辑支持;
  • 可扩展的安全认证能力,方便日志记录;
  • API 审核功能,把控所有服务;
  • 可扩展性,强大的插件开发机制;

目前常见的开源网关大致上按照语言分类有如下几类:

  • Nginx+lua:OpenResty、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

OpenResty

相关连接: 官网B站Github

OpenResty是一个流量网关,根据前面对流量网关的介绍就可以知道流量网关的指责。

OpenResty基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

通过揉和众多设计良好的 Nginx 模块,OpenResty 有效地把 Nginx 服务器转变为一个强大的 Web 应用服务器,基于它开发人员可以使用 Lua 编程语言对 Nginx 核心以及现有的各种 Nginx C 模块进行脚本编程,构建出可以处理一万以上并发请求的极端高性能的 Web 应用

OpenResty 最早是顺应 OpenAPI 的潮流做的,所以 Open 取自“开放”之意,而Resty便是 REST 风格的意思。虽然后来也可以基于 ngx_openresty 实现任何形式的 web service 或者传统的 web 应用。

也就是说 Nginx 不再是一个简单的静态网页服务器,也不再是一个简单的反向代理了。第二代的 openresty 致力于通过一系列 nginx 模块,把nginx扩展为全功能的 web 应用服务器。

ngx_openresty 是用户驱动的项目,后来也有不少国内用户的参与,从 http://openresty.org 的点击量分布上看,国内和国外的点击量基本持平。

ngx_openresty 目前有两大应用目标:

  1. 通用目的的 web 应用服务器。在这个目标下,现有的 web 应用技术都可以算是和 OpenResty 或多或少有些类似,比如 Nodejs, PHP 等等。ngx_openresty 的性能(包括内存使用和 CPU 效率)算是最大的卖点之一。
  2. Nginx 的脚本扩展编程,用于构建灵活的 Web 应用网关和 Web 应用防火墙。有些类似的是 NetScaler。其优势在于 Lua 编程带来的巨大灵活性。

Kong

相关连接: 官网Github

Kong基于OpenResty开发,也是流量层网关, 是一个云原生、快速、可扩展、分布式的Api 网关。继承了OpenResty的高性能、易扩展性等特点。Kong通过简单的增加机器节点,可以很容易的水平扩展。同时功能插件化,可通过插件来扩展其能力。而且在任何基础架构上都可以运行。具有以下特性:

  • 提供了多样化的认证层来保护Api。
  • 可对出入流量进行管制。
  • 提供了可视化的流量检查、监视分析Api。
  • 能够及时的转换请求和相应。
  • 提供log解决方案
  • 可通过api调用Serverless 函数。

Kong解决了什么问题

当我们决定对应用进行微服务改造时,应用客户端如何与微服务交互的问题也随之而来,毕竟服务数量的增加会直接导致部署授权、负载均衡、通信管理、分析和改变的难度增加。

面对以上问题,API GATEWAY是一个不错的解决方案,其所提供的访问限制、安全、流量控制、分析监控、日志、请求转发、合成和协议转换功能,可以解放开发者去把精力集中在具体逻辑的代码,而不是把时间花费在考虑如何解决应用和其他微服务链接的问题上。

图片来自Kong官网:

img

可以看到Kong解决的问题。专注于全局的Api管理策略,全局流量监控、日志记录、全局限流、黑白名单控制、接入请求到业务系统的负载均衡等。

Kong的优点以及性能

在众多 API GATEWAY 框架中,Mashape 开源的高性能高可用API网关和API服务管理层——KONG(基于 NGINX+Lua)特点尤为突出,它可以通过插件扩展已有功能,这些插件(使用 lua 编写)在API请求响应循环的生命周期中被执行。于此同时,KONG本身提供包括 HTTP 基本认证、密钥认证、CORS、TCP、UDP、文件日志、API请求限流、请求转发及 NGINX 监控等基本功能。目前,Kong 在 Mashape 管理了超过 15,000 个 API,为 200,000 开发者提供了每月数十亿的请求支持。

Kong架构

Kong提供一些列的服务,这就不得不谈谈内部的架构:

img

首先最底层是基于Nginx, Nginx是高性能的基础层, 一个良好的负载均衡、反向代理器,然后在此基础上增加Lua脚本库,形成了OpenResty,拦截请求, 响应生命周期,可以通过Lua编写脚本,所以插件比较丰富。

关于Kong的一些插件库以及如何配置,可以参考简书:开源API网关系统(Kong教程)入门到精通

Zuul1.0

Zuul是所有从设备和web站点到Netflix流媒体应用程序后端请求的前门。作为一个边缘服务应用程序,Zuul被构建来支持动态路由、监视、弹性和安全性。它还可以根据需要将请求路由到多个Amazon自动伸缩组。

Zuul使用了一系列不同类型的过滤器,使我们能够快速灵活地将功能应用到服务中。

过滤器

过滤器是Zuul的核心功能。它们负责应用程序的业务逻辑,可以执行各种任务。

  • Type : 通常定义过滤器应用在哪个阶段
  • Async : 定义过滤器是同步还是异步
  • Execution Order : 执行顺序
  • Criteria : 过滤器执行的条件
  • Action : 如果条件满足,过滤器执行的动作

Zuul提供了一个动态读取、编译和运行这些过滤器的框架。过滤器之间不直接通信,而是通过每个请求特有的RequestContext共享状态。

下面是Zuul的一些过滤器:

Incoming

Incoming过滤器在请求被代理到Origin之前执行。这通常是执行大部分业务逻辑的地方。例如:认证、动态路由、速率限制、DDoS保护、指标。

Endpoint

Endpoint过滤器负责基于incoming过滤器的执行来处理请求。Zuul有一个内置的过滤器(ProxyEndpoint),用于将请求代理到后端服务器,因此这些过滤器的典型用途是用于静态端点。例如:健康检查响应,静态错误响应,404响应。

Outgoing

Outgoing过滤器在从后端接收到响应以后执行处理操作。通常情况下,它们更多地用于形成响应和添加指标,而不是用于任何繁重的工作。例如:存储统计信息、添加/剥离标准标题、向实时流发送事件、gziping响应。

过滤器类型

下面是与一个请求典型的生命周期对应的标准的过滤器类型:

  • PRE : 路由到Origin之前执行
  • ROUTING : 路由到Origin期间执行
  • POST : 请求被路由到Origin之后执行
  • ERROR : 发生错误的时候执行

这些过滤器帮助我们执行以下功能:

  • 身份验证和安全性 : 识别每个资源的身份验证需求,并拒绝不满足它们的请求
  • 监控 : 在边缘跟踪有意义的数据和统计数据,以便给我们一个准确的生产视图
  • 动态路由 : 动态路由请求到不同的后端集群
  • 压力测试 : 逐渐增加集群的流量,以评估性能
  • 限流 : 为每种请求类型分配容量,并丢弃超过限制的请求
  • 静态响应处理 : 直接在边缘构建一些响应,而不是将它们转发到内部集群

Zuul 1.0 请求生命周期

img

Netflix宣布了通用API网关Zuul的架构转型。Zuul原本采用同步阻塞架构,转型后叫作Zuul2,采用异步非阻塞架构。Zuul2和Zuul1在架构方面的主要区别在于,Zuul2运行在异步非阻塞的框架上,比如Netty。Zuul1依赖多线程来支持吞吐量的增长,而Zuul 2使用的Netty框架依赖事件循环和回调函数。

Zuul2.0

Zuul 2.0 架构图

img

上图是Zuul2的架构,和Zuul1没有本质区别,两点变化:

  1. 前端用Netty Server代替Servlet,目的是支持前端异步。后端用Netty Client代替Http Client,目的是支持后端异步。
  2. 过滤器换了一下名字,用Inbound Filters代替Pre-routing Filters,用Endpoint Filter代替Routing Filter,用Outbound Filters代替Post-routing Filters。

Inbound Filters : 路由到 Origin 之前执行,可以用于身份验证、路由和装饰请求

Endpoint Filters : 可用于返回静态响应,否则内置的ProxyEndpoint过滤器将请求路由到Origin

Outbound Filters : 从Origin那里获取响应后执行,可以用于度量、装饰用户的响应或添加自定义header

有两种类型的过滤器:sync 和 async。因为Zuul是运行在一个事件循环之上的,因此从来不要在过滤中阻塞。如果你非要阻塞,可以在一个异步过滤器中这样做,并且在一个单独的线程池上运行,否则可以使用同步过滤器。

上文提到过Zuul2开始采用了异步模型

优势是异步非阻塞模式启动的线程很少,基本上一个CPU core上只需启一个事件环处理线程,它使用的线程资源就很少,上下文切换(Context Switch)开销也少。非阻塞模式可以接受的连接数大大增加,可以简单理解为请求来了只需要进队列,这个队列的容量可以设得很大,只要不超时,队列中的请求都会被依次处理。

不足,异步模式让编程模型变得复杂。一方面Zuul2本身的代码要比Zuul1复杂很多,Zuul1的代码比较容易看懂,Zuul2的代码看起来就比较费劲。另一方面异步模型没有一个明确清晰的请求->处理->响应执行流程(call flow),它的流程是通过事件触发的,请求处理的流程随时可能被切换断开,内部实现要通过一些关联id机制才能把整个执行流再串联起来,这就给开发调试运维引入了很多复杂性,比如你在IDE里头调试异步请求流就非常困难。另外ThreadLocal机制在这种异步模式下就不能简单工作,因为只有一个事件环线程,不是每个请求一个线程,也就没有线程局部的概念,所以对于CAT这种依赖于ThreadLocal才能工作的监控工具,调用链埋点就不好搞(实际可以工作但需要进行特殊处理)。

总体上,异步非阻塞模式比较适用于IO密集型(IO bound)场景,这种场景下系统大部分时间在处理IO,CPU计算比较轻,少量事件环线程就能处理。

Zuul 与 Zuul 2 性能对比

img

Netflix给出了一个比较模糊的数据,大致Zuul2的性能比Zuul1好20%左右,这里的性能主要指每节点每秒处理的请求数。为什么说模糊呢?因为这个数据受实际测试环境,流量场景模式等众多因素影响,你很难复现这个测试数据。即便这个20%的性能提升是确实的,其实这个性能提升也并不大,和异步引入的复杂性相比,这20%的提升是否值得是个问题。Netflix本身在其博文22和ppt11中也是有点含糊其词,甚至自身都有一些疑问的。

Spring Cloud Gateway

相关链接:官网中文官方文档

SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

Spring Cloud Gateway 底层使用了高性能的通信框架Netty

SpringCloud Gateway 特征

SpringCloud官方,对SpringCloud Gateway 特征介绍如下:

(1)基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0

(2)集成 Hystrix 断路器

(3)集成 Spring Cloud DiscoveryClient

(4)Predicates 和 Filters 作用于特定路由,易于编写的 Predicates 和 Filters

(5)具备一些网关的高级功能:动态路由、限流、路径重写

从以上的特征来说,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的区别,还是在底层的通信框架上。

简单说明一下上文中的三个术语:

Filter(过滤器)

和Zuul的过滤器在概念上类似,可以使用它拦截和修改请求,并且对上游的响应,进行二次处理。过滤器为org.springframework.cloud.gateway.filter.GatewayFilter类的实例。

Route(路由)

网关配置的基本组成模块,和Zuul的路由配置模块类似。一个Route模块由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配,目标URI会被访问。

Predicate(断言):

这是一个 Java 8 的 Predicate,可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。断言的输入类型是一个 ServerWebExchange。

几种网关的对比

img

这里比较好的产品是fizzgate,然而没有开源管理端的源代码,其实我主要需要一个管理端

An Aggregation API Gateway in Java . Fizz Gateway 是一个基于 Java开发的微服务聚合网关,是拥有自主知识产权的应用网关国产化替代方案,能够实现热服务编排聚合、自动授权选择、线上服务脚本编码、在线测试、高性能路由、API审核管理、回调管理等目的,拥有强大的自定义插件系统可以自行扩展,并且提供友好的图形化配置界面,能够快速帮助企业进行API服务治理、减少中间层胶水代码以及降低编码投入、提高 API 服务的稳定性和安全性。

花了三分钟摘抄了一下,其实有点懒。

相关文章
|
26天前
|
项目管理 微服务
云效常见问题之将多个微服务应用集成到一次研发流程中发布上线如何解决
云效(CloudEfficiency)是阿里云提供的一套软件研发效能平台,旨在通过工程效能、项目管理、质量保障等工具与服务,帮助企业提高软件研发的效率和质量。本合集是云效使用中可能遇到的一些常见问题及其答案的汇总。
25 0
|
1月前
|
数据库 Android开发 开发者
构建高性能微服务架构:从理论到实践构建高效Android应用:探究Kotlin协程的优势
【2月更文挑战第16天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力而受到企业的青睐。本文将深入探讨如何构建一个高性能的微服务系统,涵盖从理论基础到具体实现的各个方面。我们将重点讨论服务拆分策略、通信机制、数据一致性以及性能优化等关键主题,为读者提供一个清晰、实用的指南,以便在复杂多变的业务环境中构建和维护健壮的微服务体系结构。 【2月更文挑战第16天】 在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着技术的不断进步,Kotlin作为一种现代编程语言,在Android开发中被广泛采用,尤其是其协程特性为异步编程带来了革命性的改进。本文旨在深入
239 5
|
1月前
|
监控 网络协议 Go
应用监控 eBPF 版:实现 Golang 微服务的无侵入应用监控
应用监控 eBPF 版:实现 Golang 微服务的无侵入应用监控
109637 119
|
2月前
|
运维 监控 数据管理
Apollo与微服务架构:构建可扩展的应用程序
Apollo与微服务架构:构建可扩展的应用程序
|
3月前
|
微服务
微服务 乾坤子应用 内存增长 没有释放
子应用内存没有被释放,每次刷新都会增加内存增长
|
4月前
|
Java 数据安全/隐私保护 数据格式
Spring Cloud Gateway 网关整合 Knife4j 4.3 实现微服务接口文档聚合
Spring Cloud Gateway 网关整合 Knife4j 4.3 实现微服务接口文档聚合
|
30天前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
80 0
|
5天前
|
Kubernetes 监控 Cloud Native
构建高效云原生应用:基于Kubernetes的微服务治理实践
【4月更文挑战第13天】 在当今数字化转型的浪潮中,企业纷纷将目光投向了云原生技术以支持其业务敏捷性和可扩展性。本文深入探讨了利用Kubernetes作为容器编排平台,实现微服务架构的有效治理,旨在为开发者和运维团队提供一套优化策略,以确保云原生应用的高性能和稳定性。通过分析微服务设计原则、Kubernetes的核心组件以及实际案例,本文揭示了在多变的业务需求下,如何确保系统的高可用性、弹性和安全性。
11 4
|
1月前
|
运维 Go 开发者
Go语言基础及其在微服务中的应用
【2月更文挑战第14天】本文旨在探讨Go语言的核心特性及其在构建微服务架构中的实际应用。我们将首先简要介绍Go语言的基本概念与特点,然后详细分析Go语言在构建高性能、高可用微服务中的优势,并通过实例展示如何使用Go语言实现微服务的基础组件和通信机制。
|
2月前
|
Go API 开发者
探索Go语言在微服务架构中的应用
本文旨在探讨Go语言(又称Golang)在构建高性能、可扩展微服务架构中的关键作用与优势。不同于传统摘要的概述方式,我们将通过一个实际案例,揭示Go语言如何解决微服务中的并发处理和网络通信问题,以及它在微服务生态系统中的位置。通过对比其他语言,本文强调Go语言的简洁语法、出色的并发支持和高效的性能表现,为开发者提供了一种有效的工具,以应对当今微服务架构的复杂需求。