1.API网关:
(1)什么是网关?
微服务背景下,一个系统被拆分为多个服务,但是像安全认证,流量控制,日志,监控等功能是每个服务都需要的,没有网关的话,我们就需要在每个服务中单独实现,重复且零散。
实际上,网关主要做了两件事情:请求转发 + 请求过滤。
由于引入网关之后,会多一步网络转发,因此性能会有一点影响(几乎可以忽略不计)。 另外,我们需要保障网关服务的高可用,避免单点风险。
网关服务外层通过 Nginx(其他负载均衡设备/软件也行) 进⾏负载转发以达到⾼可⽤。Nginx 在部署的时候,尽量也要考虑高可用,避免单点风险。
(2)网关能提供哪些功能?
绝大部分网关可以提供下面这些功能(有一些功能需要借助其他框架或者中间件):- 请求转发:将请求转发到目标微服务。
- 负载均衡:根据各个微服务实例的负载情况或者具体的负载均衡策略配置对请求实现动态的负载均衡。
- 安全认证:对用户请求进行身份验证并仅允许可信客户端访问 API,并且还能够使用类似 RBAC 等方式来授权。
- 参数校验:支持参数映射与校验逻辑。
- 日志记录:记录所有请求的行为日志供后续使用。
- 监控告警:从业务指标、机器指标、JVM 指标等方面进行监控并提供配套的告警机制。
- 流量控制:对请求的流量进行控制,也就是限制某一时刻内的请求数。
- 熔断降级:实时监控请求的统计信息,达到配置的失败阈值后,自动熔断,返回默认值。
- 响应缓存:当用户请求获取的是一些静态的或更新不频繁的数据时,一段时间内多次请求获取到的数据很可能是一样的。对于这种情况可以将响应缓存起来。这样用户请求可以直接在网关层得到响应数据,无需再去访问业务服务,减轻业务服务的负担。
- 响应聚合:某些情况下用户请求要获取的响应内容可能会来自于多个业务服务。网关作为业务服务的调用方,可以把多个服务的响应整合起来,再一并返回给用户。
- 灰度发布:将请求动态分流到不同的服务版本(最基本的一种灰度发布)。
- 异常处理:对于业务服务返回的异常响应,可以在网关层在返回给用户之前做转换处理。这样可以把一些业务侧返回的异常细节隐藏,转换成用户友好的错误提示返回。
- API 文档: 如果计划将 API 暴露给组织以外的开发人员,那么必须考虑使用 API 文档,例如 Swagger 或 OpenAPI。
- 协议转换:通过协议转换整合后台基于 REST、AMQP、Dubbo 等不同风格和实现技术的微服务,面向 Web Mobile、开放平台等特定客户端提供统一服务。
- 证书管理:将 SSL 证书部署到 API 网关,由一个统一的入口管理接口,降低了证书更换时的复杂度。
(3)有哪些常见的网关系统?
# Netflix Zuul
Zuul 是 Netflix 开发的一款提供动态路由、监控、弹性、安全的网关服务,基于 Java 技术栈开发,可以和 Eureka、Ribbon、Hystrix 等组件配合使用。
Zuul 主要通过过滤器(类似于 AOP)来过滤请求,从而实现网关必备的各种功能。
我们可以自定义过滤器来处理请求,并且,Zuul 生态本身就有很多现成的过滤器供我们使用,一般是配合 hystrix 来做限流。
Zuul1.x基于同步 IO,性能较差。Zuul2.x基于 Netty 实现了异步 IO,性能得到了大幅改进。
# Spring Cloud Gateway
SpringCloud Gateway 属于 Spring Cloud 生态系统中的网关,其诞生的目标是为了替代老牌网关 Zuul。准确点来说,应该是 Zuul 1.x。
为了提升网关的性能,SpringCloud Gateway 基于 Spring WebFlux 。Spring WebFlux 使用 Reactor 库来实现响应式编程模型,底层基于 Netty 实现同步非阻塞的 I/O。
Spring Cloud Gateway 不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,限流。
Spring Cloud Gateway 和 Zuul 2.x 的差别不大,也是通过过滤器来处理请求。不过,目前更加推荐使用 Spring Cloud Gateway 而非 Zuul,Spring Cloud 生态对其支持更加友好。
# OpenResty
OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty 基于 Nginx,主要还是看中了其优秀的高并发能力。不过,由于 Nginx 采用 C 语言开发,二次开发门槛较高。如果想在 Nginx 上实现一些自定义的逻辑或功能,就需要编写 C 语言的模块,并重新编译 Nginx。
为了解决这个问题,OpenResty 通过实现 ngx_lua
和 stream_lua
等 Nginx 模块,把 Lua/LuaJIT 完美地整合进了 Nginx,从而让我们能够在 Nginx 内部里嵌入 Lua 脚本,使得可以通过简单的 Lua 语言来扩展网关的功能,比如实现自定义的路由规则、过滤器、缓存策略等。
Lua 是一种非常快速的动态脚本语言,它的运行速度接近于 C 语言。
LuaJIT 是 Lua 的一个即时编译器,它可以显著提高 Lua 代码的执行效率。
LuaJIT 将一些常用的 Lua 函数和工具库预编译并缓存,这样下次调用就可以直接使用缓存的字节码,大大加快了执行速度。
# Kong
Kong 是一款基于 OpenResty(Nginx + Lua)的高性能、云原生、可扩展、生态丰富的网关系统,主要由 3 个组件组成:
- Kong Server:基于 Nginx 的服务器,用来接收 API 请求。
- Apache Cassandra/PostgreSQL:用来存储操作数据。
- Kong Dashboard:官方推荐 UI 管理工具,当然,也可以使用 RESTful 方式 管理 Admin api。
由于默认使用 Apache Cassandra/PostgreSQL 存储数据,Kong 的整个架构比较臃肿,并且会带来高可用的问题。
Kong 提供了插件机制来扩展其功能,插件在 API 请求响应循环的生命周期中被执行。比如在服务上启用 Zipkin 插件:
Kong 本身就是一个 Lua 应用程序,并且是在 Openresty 的基础之上做了一层封装的应用。归根结底就是利用 Lua 嵌入 Nginx 的方式,赋予了 Nginx 可编程的能力,这样以插件的形式在 Nginx 这一层能够做到无限想象的事情。例如限流、安全访问策略、路由、负载均衡等等。编写一个 Kong 插件,就是按照 Kong 插件编写规范,写一个自己自定义的 Lua 脚本,然后加载到 Kong 中,最后引用即可。除了 Lua,Kong 还可以基于 Go 、JavaScript、Python 等语言开发插件,得益于对应的 PDK(插件开发工具包)。# APISIX
APISIX 是一款基于 OpenResty 和 etcd 的高性能、云原生、可扩展的网关系统。
etcd 是使用 Go 语言开发的一个开源的、高可用的分布式 key-value 存储系统,使用 Raft 协议做分布式共识。
与传统 API 网关相比,APISIX 具有动态路由和插件热加载,特别适合微服务系统下的 API 管理。并且,APISIX 与 SkyWalking(分布式链路追踪系统)、Zipkin(分布式链路追踪系统)、Prometheus(监控系统) 等 DevOps 生态工具对接都十分方便。
作为 Nginx 和 Kong 的替代项目,APISIX 目前已经是 Apache 顶级开源项目,并且是最快毕业的国产开源项目。国内目前已经有很多知名企业(比如金山、有赞、爱奇艺、腾讯、贝壳)使用 APISIX 处理核心的业务流量。
根据官网介绍:“APISIX 已经生产可用,功能、性能、架构全面优于 Kong”。
APISIX 同样支持定制化的插件开发。开发者除了能够使用 Lua 语言开发插件,还能通过下面两种方式开发来避开 Lua 语言的学习成本:
- 通过 Plugin Runner 来支持更多的主流编程语言(比如 Java、Python、Go 等等)。通过这样的方式,可以让后端工程师通过本地 RPC 通信,使用熟悉的编程语言开发 APISIX 的插件。这样做的好处是减少了开发成本,提高了开发效率,但是在性能上会有一些损失。
- 使用 Wasm(WebAssembly) 开发插件。Wasm 被嵌入到了 APISIX 中,用户可以使用 Wasm 去编译成 Wasm 的字节码在 APISIX 中运行。
Wasm 是基于堆栈的虚拟机的二进制指令格式,一种低级汇编语言,非常接近已编译的机器代码,和本机性能。
Wasm 最初是为浏览器构建的,但是随着技术的成熟,在服务器端看到了越来越多的用例。
# Shenyu
Shenyu 是一款基于 WebFlux 的可扩展、高性能、响应式网关,Apache 顶级开源项目。
Shenyu 通过插件扩展功能,插件是 ShenYu 的灵魂,并且插件也是可扩展和热插拔的。不同的插件实现不同的功能。Shenyu 自带了诸如限流、熔断、转发、重写、重定向、和路由监控等插件。
(4)如何选择?
最常用的是 Spring Cloud Gateway、Kong、APISIX 。
对于业务以 Java 为主要开发语言的情况,Spring Cloud Gateway 通常是个不错的选择,其优点有:简单易用、成熟稳定、与 Spring Cloud 生态系统兼容、Spring 社区成熟等等。不过,Spring Cloud Gateway 也有一些局限性, 一般还需要结合其他网关一起使用比如 OpenResty。并且,其性能相比较于 Kong 和 APISIX,还是差一些。
如果对性能要求比较高的话,Kong 和 APISIX 功能更丰富,性能更强大,技术架构更贴合云原生。Kong 是开源 API 网关的鼻祖,生态丰富,用户群体庞大。APISIX 属于后来者,更优秀一些,根据 APISIX 官网介绍:“APISIX 已经生产可用,功能、性能、架构全面优于 Kong”。
- APISIX 基于 etcd 来做配置中心,不存在单点问题,云原生友好;而 Kong 基于 Apache Cassandra/PostgreSQL ,存在单点风险,需要额外的基础设施保障做高可用。
- APISIX 支持热更新,并且实现了毫秒级别的热更新响应;而 Kong 不支持热更新。
- APISIX 的性能要优于 Kong 。
- APISIX 支持的插件更多,功能更丰富。
2.SpringCloud Gateway
(1) 什么是 Spring Cloud Gateway?
Spring Cloud Gateway 属于 Spring Cloud 生态系统中的网关,其诞生的目标是为了替代老牌网关 Zuul (Zuul 1.x)。
为了提升网关的性能,Spring Cloud Gateway 基于 Spring WebFlux 。Spring WebFlux 使用 Reactor 库来实现响应式编程模型,底层基于 Netty 实现同步非阻塞的 I/O。
Spring Cloud Gateway 不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,限流。
Spring Cloud Gateway 和 Zuul 2.x 的差别不大,也是通过过滤器来处理请求。不过,目前更加推荐使用 Spring Cloud Gateway 而非 Zuul,Spring Cloud 生态对其支持更加友好。
(2)Spring Cloud Gateway 的工作流程?
Spring Cloud Gateway 的工作流程如下图所示:
具体流程:
- 路由判断:客户端的请求到达网关后,先经过 Gateway Handler Mapping 处理,这里面会做断言(Predicate)判断,看下符合哪个路由规则,这个路由映射后端的某个服务。
- 请求过滤:然后请求到达 Gateway Web Handler,这里面有很多过滤器,组成过滤器链(Filter Chain),这些过滤器可以对请求进行拦截和修改,比如添加请求头、参数校验等等,有点像净化污水。然后将请求转发到实际的后端服务。这些过滤器逻辑上可以称作 Pre-Filters,Pre 可以理解为“在...之前”。
- 服务处理:后端服务会对请求进行处理。
- 响应过滤:后端处理完结果后,返回给 Gateway 的过滤器再次做处理,逻辑上可以称作 Post-Filters,Post 可以理解为“在...之后”。
- 响应返回:响应经过过滤处理后,返回给客户端。
(3) Spring Cloud Gateway 的断言是什么?
断言(Predicate): 就是对一个表达式进行 if 判断,结果为真或假,如果为真则做这件事,否则做那件事。
在 Gateway 中,如果客户端发送的请求满足了断言的条件,则映射到指定的路由器,就能转发到指定的服务上进行处理。
断言配置的示例如下,配置了两个路由规则,有一个 predicates 断言配置,当请求 url 中包含 api/thirdparty
,就匹配到了第一个路由 route_thirdparty
。
常见路由断言规则:
(4)Spring Cloud Gateway 的路由和断言是什么关系?
Route 路由和 Predicate 断言的对应关系如下::
- 一对多:一个路由规则可以包含多个断言。如上图中路由 Route1 配置了三个断言 Predicate。
- 同时满足:如果一个路由规则中有多个断言,则需要同时满足才能匹配。如上图中路由 Route2 配置了两个断言,客户端发送的请求必须同时满足这两个断言,才能匹配路由 Route2。
- 第一个匹配成功:如果一个请求可以匹配多个路由,则映射第一个匹配成功的路由。如上图所示,客户端发送的请求满足 Route3 和 Route4 的断言,但是 Route3 的配置在配置文件中靠前,所以只会匹配 Route3。
(5)Spring Cloud Gateway 如何实现动态路由?
在使用 Spring Cloud Gateway 的时候,官方提供的方案总是基于配置文件或代码配置的方式。
Spring Cloud Gateway 作为微服务的入口,需要尽量避免重启,而现在配置更改需要重启服务不能满足实际生产过程中的动态刷新、实时变更的业务需求,所以我们需要在 Spring Cloud Gateway 运行时动态配置网关。
实现动态路由的方式有很多种,其中一种推荐的方式是基于 Nacos 注册中心来做。 Spring Cloud Gateway 可以从注册中心获取服务的元数据(例如服务名称、路径等),然后根据这些信息自动生成路由规则。这样,当你添加、移除或更新服务实例时,网关会自动感知并相应地调整路由规则,无需手动维护路由配置。
其实这些复杂的步骤并不需要我们手动实现,通过 Nacos Server 和 Spring Cloud Alibaba Nacos Config 即可实现配置的动态变更。
(6)Spring Cloud Gateway 的过滤器有哪些?
过滤器 Filter 按照请求和响应可以分为两种:
- Pre 类型:在请求被转发到微服务之前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等操作。
- Post 类型:微服务处理完请求后,返回响应给网关,网关可以再次进行处理,例如修改响应内容或响应头、日志输出、流量监控等。
另外一种分类是按照过滤器 Filter 作用的范围进行划分:
- GatewayFilter:局部过滤器,应用在单个路由或一组路由上的过滤器。标红色表示比较常用的过滤器。
- GlobalFilter:全局过滤器,应用在所有路由上的过滤器。
局部过滤器具体使用:
filters: #过滤器 - RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的 “api” 替换成空
全局过滤器最常见的用法是进行负载均衡。配置如下所示:
spring: cloud: gateway: routes: - id: route_member # 第三方微服务路由规则 uri: lb://passjava-member # 负载均衡,将请求转发到注册中心注册的 passjava-member 服务 predicates: # 断言 - Path=/api/member/** # 如果前端请求路径包含 api/member,则应用这条路由规则 filters: #过滤器 - RewritePath=/api/(?<segment>.*),/$\{segment} # 将跳转路径中包含的api替换成空
这里有个关键字 lb
,用到了全局过滤器 LoadBalancerClientFilter
,当匹配到这个路由后,会将请求转发到 passjava-member 服务,且支持负载均衡转发,也就是先将 passjava-member 解析成实际的微服务的 host 和 port,然后再转发给实际的微服务。
(7)Spring Cloud Gateway 支持限流吗?
Spring Cloud Gateway 自带了限流过滤器,对应的接口是 RateLimiter
,RateLimiter
接口只有一个实现类 RedisRateLimiter
(基于 Redis + Lua 实现的限流),提供的限流功能比较简易且不易使用。
从 Sentinel 1.6.0 版本开始,Sentinel 引入了 Spring Cloud Gateway 的适配模块,可以提供两种资源维度的限流:route 维度和自定义 API 维度。也就是说,Spring Cloud Gateway 可以结合 Sentinel 实现更强大的网关流量控制.
(8)Spring Cloud Gateway 如何自定义全局异常处理?
在 SpringBoot 项目中,我们捕获全局异常只需要在项目中配置 @RestControllerAdvice
和 @ExceptionHandler
就可以了。不过,这种方式在 Spring Cloud Gateway 下不适用。
Spring Cloud Gateway 提供了多种全局处理的方式,比较常用的一种是实现ErrorWebExceptionHandler
并重写其中的handle
方法。
@Order(-1) @Component @RequiredArgsConstructor public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler { private final ObjectMapper objectMapper; @Override public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) { // ... } }
标签:网关,请求,Spring,API,路由,Gateway,Cloud From: https://www.cnblogs.com/cjhtxdy/p/17891503.html