irpas技术客

【SpringCloud】SpringCloud之微服务网关GateWay_童话ing_springcloud微服务网关

大大的周 3372

文章目录 前言一、SpringCloud GateWay概述1.1 Zuul1.x的缺陷1.2 Spring WebFlux1.3 GateWay工作流程 二、GateWay实战2.1 Spring Cloud Gateway中的Predicate介绍2.2 Spring Cloud Gateway中的Filter介绍2.2.1 自定义全局GlobalFilter 三、总结

前言

通过前面知识的学习,我们已经可以基本搭建出一套微服务架构了,我们有注册中心 EurekaSpringCloud整合Eurea注册中心基础知识或者NacosNacos特性介绍以及SpringCloud Alibaba整合Nacos案例,可以将服务注册到注册中心中进行管理,我们有 Ribbon 或FeignSpringCloud之Ribbon及Feign介绍 可以实现对服务负载均衡地调用,我们有 Hystrix/Sentinel SpringCloud Alibaba组件Sentinel探索之旅可以实现服务的熔断、限流降级,但是我们还缺少什么呢?我们先来看一个基础的微服务架构图: 在上面的架构图中,我们的服务包括:内部服务 Service A 和内部服务 ServiceB,这两个服务都是集群部署,每个服务部署了 3 个实例,他们都会通过 Eureka Server 注册中心注册与订阅服务,而 Open Service 是一个对外的服务,也是集群部署,外部调用方通过负载均衡设备调用 Open Service 服务,比如负载均衡使用 Nginx,这样的实现是否合理,或者是否有更好的实现方式呢?带着上面的疑惑,我们来考虑这样的几个问题:

首先,如果我们的微服务中有很多个独立服务都要对外提供服务,那么我们要如何去管理这些接口?特别是当项目非常庞大的情况下要如何管理?

其次,在微服务中,一个独立的系统被拆分成了很多个独立的服务,为了确保安全,权限管理也是一个不可回避的问题,如果在每一个服务上都添加上相同的权限验证代码来确保系统不被非法访问,那么工作量也就太大了,而且维护也非常不方便。

为了解决上述问题,微服务架构中提出了 API 网关的概念,它就像一个安检站一样,所有外部的请求都需要经过它的调度与过滤,然后 API 网关来实现请求路由、负载均衡、权限验证等功能;

Spring Cloud 这个一站式的微服务开发框架基于 Netflix Zuul 实现了Spring Cloud Zuul,采用 Spring Cloud Zuul 即可实现一套 API 网关服务。其官网地址为:Netflix/zuul,但是在在Spring Cloud 2.0以上版本中,没有对新版本的Zul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。虽然Netflix早就发布了最新的Zuul 2.x,但SpringCloud貌似没有整合计划。而且Netflix相关组件都宣布进入维护期;不知前景如何?SpringCloud自己研发了一个网关替代Zuul,那就是SpringCloud Gateway,在本文中,也主要是探索SpringCloud GateWay的使用和原理。Gateway是基于异步非阻塞模型上进行开发的,性能方面不需要担心。

一、SpringCloud GateWay概述

Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5.0+Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供—种简单有效的统一的API路由管理方式。SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。目标是提供统一的路由方式且基于 Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。官网地址:Spring Cloud Gateway

此时,我们便可以进行微服务架构的调整,请求经过负载均衡组件如Nginx之后,再通过网关的过滤和路由,交给各个微服务去执行。 这样,我们在网关这层就能对请求进行过滤,如进行权限控制,请求路由等等。

SpringCloud Gateway具有如下特性:

基于Spring Framework 5,Project Reactor和Spring Boot 2.0进行构建;动态路由:能够匹配任何请求属性;可以对路由指定Predicate (断言)和Filter(过滤器);集成Hystrix的断路器功能;集成Spring Cloud 服务发现功能;易于编写的Predicate (断言)和Filter (过滤器);请求限流功能;支持路径重写。 1.1 Zuul1.x的缺陷

在讨论GateWay之前,我们先来看看Zuul1.x的涉及缺陷:

SpringCloud中所集成的Zuul版本,采用的是Tomcat容器,使用的是传统的Serviet IO处理模型。其主要生命周期如下:

container启动时构造servlet对象,并调用init()进行初始化。container运行时接受请求,并为每个请求分配一个线程(一般从线程池中获取空闲线程)然后调用service)。container关闭时调用destory()方法销毁servlet。

Servlet是一个简单的网络IO模型,当请求进入Servlet container时,Servlet container就会为其绑定一个线程,在并发不高的场景下这种模型是适用的。但是一旦出现高并发,线程数量就会上涨,而线程资源代价是昂贵的(上线文切换,内存消耗大)严重影响请求的处理时间。在一些简单业务场景下,不希望为每个request分配一个线程,只需要1个或几个线程就能应对极大并发的请求,这种业务场景下servlet模型没有优势。

所以Zuul 1.X是基于Servlet之上的一个阻塞式处理模型,即Spring实现了处理所有request请求的一个Servlet (DispatcherServlet)并由该servlet阻塞式处理处理。所以SpringCloud Zuul无法摆脱Servlet模型的弊端。虽然Netflix早就发布了最新的Zuul 2.x,但Spring Cloud貌似没有整合计划。而且Netflix相关组件都宣布进入维护期。

1.2 Spring WebFlux

传统的Web框架,比如说: Struts2,SpringMVC等都是基于Servlet APl与Servlet容器基础之上运行的。但是在Servlet3.1之后有了异步非阻塞的支持。而WebFlux Spring WebFlux是一个典型非阻塞异步的框架,它的核心是基于Reactor的相关API实现的。相对于传统的web框架来说,它可以运行在诸如Netty,Undertow及支持Servlet3.1的容器上。非阻塞式+函数式编程(Spring 5必须让你使用Java 8)。

Spring WebFlux是Spring 5.0 引入的新的响应式框架,区别于Spring MVC,它不需要依赖Servlet APl,它是完全异步非阻塞的,并且基于Reactor来实现响应式流规范。

1.3 GateWay工作流程

在SpringCloud GateWay中,主要包含三个核心的概念:

Route(路由) : 路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如断言为true则匹配该路由。Predicate(断言) : 参考的是Java8的java.util.function.Predicate,开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。Filter(过滤) : 指的是Spring框架中Gateway Filter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。

Route可以理解为当web请求到达微服务之前,通过一些匹配条件,定位到真正的服务节点。并在这个请求转发过程的前后,进行一些精细化控制。Route的功能完成离不开Predicate和Filter的配合,Predicate就是我们的匹配条件,Filter,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri,就可以实现一个具体的路由了。

因此整个GateWay的工作流程为:客户端向 Spring Cloud Gateway 发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关 Web 处理程序。此处理程序通过特定于请求的过滤器链运行请求。过滤器被虚线分隔的原因是过滤器可以在发送代理请求之前和之后运行逻辑。执行所有“预”过滤器逻辑。然后进行代理请求。发出代理请求后,将运行“post”过滤器逻辑。

核心还是两个部分,其一是进行路由转发,其二是执行过滤器链。

客户端向Spring Cloud Gateway发出请求。在Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到Gateway Web Handler。Handler再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。

图中,过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post")执行业务逻辑。Filter在“pre”类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。

至此,概念就已经介绍得差不多了,下面一节我们将实际搭建微服务进行实践。

二、GateWay实战

在本次实战中,我们需要利用之前使用的服务Payment 8001和注册中心Eureka 7001、Eureka 7002,这两个的搭建我们在介绍Eureka时候已经实战过了,因此这里会复用之前的代码,地址为:SpringCloud整合Eurea注册中心基础知识

然后我们再搭建一个9527的微服务网关,其依赖如下:

<dependencies> <!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--eureka-client--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <!-- 引入自己定义的api通用包,可以使用Payment支付Entity --> <dependency> <groupId>com.dl.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>${project.version}</version> </dependency> <!--一般基础配置类--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>

微服务网关GateWay也会作为一个服务注册进入Eureka注册中心中,yml配置文件或者properties配置文件:

server.port=9527 #微服务名称 spring.application.name=cloud-gateway ################################网关配置############################## #路由ID,没有固定规则但要求唯一,建议配合服务名 spring.cloud.gateway.routes[0].id=payment-routh #匹配后提供服务的路由地址,固定地址方式 #spring.cloud.gateway.routes[0].uri=http://localhost:8001/ #动态路由方式,其中lb://serviceName是spring cloud gateway在微服务中自动为我们创建的负载均衡uri。 spring.cloud.gateway.routes[0].uri=lb://cloud-payment-service #断言,路径相匹配进行路由,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。 spring.cloud.gateway.routes[0].predicates[0]=Path=/payment/get/** #spring.cloud.gateway.routes[0].predicates[0]=Between/After=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver],通过ZonedDateTime.now(); 获取时区 #spring.cloud.gateway.routes[0].predicates[0]=Cookie=chocolate, ch.p http://localhost:9527/payment/lb --cookie "chocolate=chip" #spring.cloud.gateway.routes[0].predicates[0]=Header=X-Request-Id, \d+ http://localhost:9527/payment/lb -H "X-Request-Id:123" spring.cloud.gateway.routes[1].id=payment-routh2 #spring.cloud.gateway.routes[1].uri=http://localhost:8001/ spring.cloud.gateway.routes[1].uri=lb://cloud-payment-service spring.cloud.gateway.routes[1].predicates[0]=Path=/payment/lb/** #eureka实例名称 eureka.instance.hostname=cloud-gateway-service #注册进入eureka eureka.client.register-with-eureka=true #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 eureka.client.fetch-registry=true #Eureka集群 eureka.client.service-url.defaultZone=http://eureka7001.com:7001/eureka/

yml方便查看层次关系:

server: port: 9527 spring: application: name: cloud-gateway ###########################网关配置################################ cloud: gateway: routes: - id: payment-routh #路由ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 #uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/get/** # 断言,路径相匹配进行路由 - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名 uri: http://localhost:8001 #匹配后提供服务的路由地址 #uri: lb://cloud-payment-service #匹配后提供服务的路由地址 predicates: - Path=/payment/lb/** # 断言,路径相匹配的进行路由 ##################eureka配置########################## eureka: instance: hostname: cloud-gateway-service client: service-url: register-with-eureka: true fetch-registry: true defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

主启动类:

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class GateWay9527Application { public static void main(String[] args) { SpringApplication.run(GateWay9527Application.class,args); } }

接下来就对配置文件中的配置进行解释,在微服务网关GateWay的配置中,我们可以看到这样的一段配置: 注释中已经写得很清楚了,在微服务cloud-provider-payment8001中有一个/payment/get的接口,我们并不想直接暴露8001端口,希望在8001外面套一层9527,客户端请求通过请求9527路由到8001下的某个接口中,因此在这里做了一个路由配置,其id为payment-routh,当用户的请求与predicates中的Path匹配之后,就进行相应的路由,此时是路由到本机下的8001端口。

当然,在properties中,我做了一点改变,这是因此yml中的配置uri为一个固定得地址,这在服务为集群部署环境下不是很实用,因此需要做动态路由,直接配置微服务名,相应的协议需要改为lb,这一点是需要注意的。

因此,做了网关路由配置之后,我们便可以做如下测试, 将注册中心7001、7002、cloud-provider-payment8001和9527依次启动之后进行访问测试:

直接访问8001微服务:http://localhost:8001/payment/get?id=1 通过网关进行路由:http://localhost:9527/payment/get?id=1

两者测试能得到相同的结果,说明正常,配置文件中的第二个路由规则/payment/lb/**可自行搭建进行测试。

此外,我们的路由规则不仅可以在配置文件中进行配置,路由规则我们也可以在Java代码中进行配置实现路由:

如下实现了添加/guonei的路由到http://news.baidu.com/guonei因此,访问http://localhost:9527/guonei,和访问http://news.baidu.com/guonei返回相同的页面。

import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class GateWayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){ RouteLocatorBuilder.Builder routes=routeLocatorBuilder.routes(); routes.route("path_route_dl", route->route.path("/guonei").uri("http://news.baidu.com/guonei")).build(); return routes.build(); } } 2.1 Spring Cloud Gateway中的Predicate介绍

通过上面的配置,我们知道Predicate在网关中起着重要的作用,下面介绍一下常用的Predicate:

Spring Cloud Gateway包括许多内置的Route Predicate工厂。官方文档:Predicate官方文档所有这些Predicate都与HTTP请求的不同属性匹配。多个RoutePredicate工厂可以进行组合。Spring Cloud Gateway在创建Route 对象时,使用RoutePredicateFactory 创建 Predicate对象,Predicate 对象可以赋值给Route。Spring Cloud Gateway包含许多内置的Route Predicate Factories。所有这些谓词都匹配HTTP请求的不同属性。多种谓词工厂可以组合,并通过逻辑and。

常用的Predicate Factory主要如下:

The After Route Predicate Factory The Before Route Predicate Factory The Between Route Predicate Factory The Cookie Route Predicate Factory The Header Route Predicate Factory The Host Route Predicate Factory The Method Route Predicate Factory The Path Route Predicate Factory The Query Route Predicate Factory The RemoteAddr Route Predicate Factory The weight Route Predicate Factory

接下来我们选取其中的一些来了解一下这些常用的规则:

1、After Route Predicate Factory:after 路由谓词工厂接受一个参数,一个日期时间。此谓词匹配在指定日期时间之后发生的请求。以下示例配置了一个 after 路由谓词:

spring: cloud: gateway: routes: - id: after_route uri: https://example.org predicates: # 这个时间后才能起效 - After=2017-01-20T17:42:47.789-07:00[America/Denver]

上述配置中的路由规则after_route需要在- After中配置的时间过后才能生效,要获得上述时间,可以利用java.time.ZonedDateTime来进行获取:

ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区,2022-01-03T15:51:37.485+08:00[Asia/Shanghai]

2、Between Route Predicate Factory:路由谓词工厂之间有两个参数,datetime1和datetime2。此谓词匹配发生在 之后datetime1和之前的请求datetime2。该datetime2参数必须是后datetime1。以下示例配置了一个 between 路由谓词:

spring: cloud: gateway: routes: - id: between_route uri: https://example.org # 两个时间点之间 predicates: - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

此路由匹配 2017 年 1 月 20 日 17:42 美国时间(Denver)之后和 2017 年 1 月 21 日 17:42之前的任何请求。这对于维护窗口可能很有用。

3、Cookie Route Predicate Factory:cookie 路由谓词工厂接受两个参数,cookie 名称和正则表达式。此谓词匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置 cookie 路由谓词工厂:

spring: cloud: gateway: routes: - id: cookie_route uri: https://example.org predicates: - Cookie=chocolate, ch.p

此路由匹配具有名为 cookie 的请求,该 cookiechocolate的值与ch.p正则表达式匹配。这类测试我么可以使用curl请求进行测试:

# 该命令相当于发get请求,且没带cookie curl http://localhost:9527/payment/get?id=1 # 带cookie的 curl http://localhost:9527/payment/get?id=1 --cookie "chocolate=chip"

4、Header Route Predicate Factory:Header路由谓词工厂采用两个参数,Header名称和正则表达式。此谓词与具有给定名称的Header匹配,其值与正则表达式匹配。以下示例配置Header路由谓词:

spring: cloud: gateway: routes: - id: header_route uri: https://example.org predicates: - Header=X-Request-Id, \d+

如果请求具有名称X-Request-Id与且\d+正则表达式匹配的标头(即,它具有一位或多位数字的值),则此路由匹配。 同样地,我们可以使用请求进行测试:

# 带指定请求头的参数的CURL命令 curl http://localhost:9527/payment/get?id=1 -H "X-Request-Id:123"

5、Host Route Predicate Factory:主机路由谓词工厂采用参数为主机名模式列表。该模式是一个 Ant 风格的模式,.作为分隔符。此谓词匹配Host与模式匹配的标头。以下示例配置主机路由谓词:

spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Host=**.somehost.org,**.anotherhost.org

如果请求具有这种路由匹配Host用的头值www.somehost.org或beta.somehost.org或www.anotherhost.org。

6、Path Route Predicate Factory:Path类型的Predicate Factory接受两个参数:一个 SpringPathMatcher模式列表和一个可选标志matchOptionalTrailingSeparator。以下示例配置路径路由谓词:

spring: cloud: gateway: routes: - id: host_route uri: https://example.org predicates: - Path=/red/{segment},/blue/{segment}

此种匹配规则匹配请求路径为:/red/1、 /red/blue和/blue/green的请求,如果请求为/red/blue,那么最终会匹配规则/blue/{segment}。 7、RemoteAddr Route Predicate Factory:RemoteAddr 路由谓词工厂采用 CIDR 表示法(IPv4 或 IPv6)字符串的列表(最小大小 1),例如192.168.0.1/16(其中192.168.0.1是 IP 地址,16是子网掩码)。以下示例配置 RemoteAddr 路由谓词:

spring: cloud: gateway: routes: - id: remoteaddr_route uri: https://example.org predicates: - RemoteAddr=192.168.1.1/24

上述规则中,IPv4地址的最后8位为主机地址,因为前24位为子网掩码,因此远程请求192.168.1.10就满足匹配上面的路由规则 ,在同一子网之下。

8、Weight Route Predicate Factory:权重路由谓词工厂有两个参数:group和weight。每组计算重量。以下示例配置权重路由谓词:

spring: cloud: gateway: routes: - id: weight_high uri: https://weighthigh.org predicates: - Weight=group1, 8 - id: weight_low uri: https://weightlow.org predicates: - Weight=group1, 2

在上述配置规则中,大约80%的流量都会路由到weighthigh.org中,大约20%的流量将会路由到weightlow.org中。 9、The Query Route Predicate Factory:查询路由谓词工厂有两个参数:一个 必须的param(请求参数)和一个可选参数regexp(正则表达式)。以下示例配置查询路由谓词:

spring: cloud: gateway: routes: - id: query_route uri: https://example.org predicates: - Query=red, gree.

如果请求参数包含red并且其值与正则表达式gree.匹配,则前面的路由匹配,因此green和greet将匹配。

2.2 Spring Cloud Gateway中的Filter介绍

路由过滤器可用于修改进入的HTTP请求和返回的HTTP响应,路由过滤器只能对指定路由进行使用。Spring Cloud Gateway内置了多种路由过滤器,他们都由GatewayFilter的工厂类来产生。 GatewayFilter 种类非常多,有31种,GlobalFilter 有10种,其中常用的GatewayFilter为AddRequestParameter GatewayFilter Factory:该Filter接受名称和值参数。

spring: cloud: gateway: routes: - id: add_request_parameter_route uri: https://example.org filters: - AddRequestParameter=red, blue

上述示例中将为所有匹配请求的下游请求的查询字符串添加red=blue的参数。

AddRequestParameter也能用于匹配路径或主机的 URI 变量。URI 变量可以在值中使用并在运行时扩展。以下示例配置AddRequestParameter GatewayFilter使用变量的例子:

spring: cloud: gateway: routes: - id: add_request_parameter_route uri: https://example.org predicates: - Host: {segment}.myhost.org filters: - AddRequestParameter=foo, bar-{segment} 2.2.1 自定义全局GlobalFilter

全局的GlobalFilter接口具有与相同的签名,这些是有条件地应用于所有路由的过滤器。自定义全局的GlobalFilter主要关键为GlobalFilter、Ordered两大接口。通过实现GlobalFilter接口重写其中的filter逻辑实现过滤,而Ordered接口中的getOrder()方法能指明过滤器链的调用顺序。当请求与路由匹配时,过滤 Web 处理程序会将 的所有实例GlobalFilter和所有特定GatewayFilter于路由的实例添加到过滤器链中。这个组合过滤器链是按Ordered接口排序的,你可以通过实现getOrder()方法来设置。

由于 Spring Cloud Gateway 区分过滤器逻辑执行的“pre”和“post”阶段,具有最高优先级的过滤器是第一个“pre”阶段,最后一个“post”阶段。

如下配置了一个全局的Filter,使得所有通过网关的请求都需要携带参数uname。

import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.util.Date; @Configuration @Slf4j public class MyLogGateWayFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { log.info("***************come in MyLogGateWayFilter: "+new Date()); String uName=exchange.getRequest().getQueryParams().getFirst("uname"); if(uName==null){ log.info("*************用户名为null,非法访问!"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } } 三、总结

本文首先对微服务架构中使用网关必要性进行概述,在对比了两种主要的API网关技术Zuul 1.x和Spring Cloud GateWay之后,体现出Spring Cloud GateWay的好处,然后对Spring Cloud GateWay进行了详细探索,大部分资料借助于官方文档,再结合实际例子进行阐述,最后对SpringCloud GateWay的三大核心Router、Predicate 和Filter进行了详细探索。


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #Gateway概述11 #Zuul1x的缺陷12 #Spring #WebFlux13