Spring Cloud Gateway

发布时间:2025-12-09 17:31:20 浏览次数:4

Spring Cloud Gateway

  • 关于
  • Spring Cloud Gateway 特性
    • 1. 基于Spring Framework 5, Project Reactor以及Spring Boot 2.0构建
      • ```Project Reactor是什么?```
      • ```Reactor和Spring的关系```
      • 关于Spring 的Reactive
    • 2. Able to match routes on any request attribute.
      • ```如何引入Spring Cloud Gateway```
      • 示例
      • ```路由中uri格式为:ip + 端口或者其他等价形式:域名、lb:微服务名称```
      • ```Spring Cloud Gateway中配置负载均衡```
      • Spring Cloud Gateway顶层工作原理
    • 3. Predicates and filters are specific to routes.
      • ==**Route:**==
      • ==**Predicate:**==
      • ==**Filter**==:
    • 4 Circuit Breaker integration
      • ```为什么需要熔断降级```
      • **Spring Cloud专门用于处理熔断降级的网关过滤器工厂:** ```CircuitBreaker```**的用法**
        • **官网介绍:**
          • 1 说明
          • 2 引入熔断器依赖,并简单测试
          • 3 添加fallbackuri配置
          • 4 fallbackUri添加变量
          • 5 fallbakcUri可以指向自己服务的一个地址,也可以指向外部服务(通过路由转发)
    • 5 Spring Cloud DiscoveryClient integration
    • 6 Easy to write Predicates and Filters
    • 7 Request Rate Limiting
    • 8 Path Rewriting
  • 以上都是使用yaml配置文件,也可以使用java代码完成配置
  • 参考:

关于

什么是Spring Cloud Gateway?

This project provides a library for building an API Gateway on top of Spring WebFlux. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.

翻译:

  • Spring Cloud Gateway是基于Spring WebFlux构建的API 网关。
    什么是 Spring WebFlux? : 从功能和使用上来讲,可以理解为类似SpringMvc,但是比SpringMvc更高级,更先进;从更新迭代上来讲,可以理解为是SpringMvc的替代品。
  • Spring Cloud Gateway提供了一种简单且有效的路由方式
  • Spring Cloud Gateway也提供了一些切面关注点,例如:安全,监控/指标和弹性(限流)。

Spring Cloud Gateway 特性

也可以理解为Spring Cloud Gateway 大致包含的内容有哪些。

  • Built on Spring Framework 5, Project Reactor and Spring Boot 2.0

  • Able to match routes on any request attribute.

  • Predicates and filters are specific to routes.

  • Circuit Breaker integration.

  • Spring Cloud DiscoveryClient integration

  • Easy to write Predicates and Filters

  • Request Rate Limiting

  • Path Rewriting

  • 1. 基于Spring Framework 5, Project Reactor以及Spring Boot 2.0构建

    Project Reactor是什么?

    Reactor is a fourth-generation reactive library, based on the Reactive Streamsspecification, for building non-blocking applications on the JVM

    Reactor是一个第四代响应式编程类库,它是基于响应式流规范的,用于在JVM上构建非阻塞应用。

    参考:
    1. https://projectreactor.io/
    2. https://spring.io/reactive

    Reactor和Spring的关系

    先看看Reactor响应式编程类库有什么特性(优势)?
    Reactor响应式系统非常适合低延迟、高吞吐量场景的工作负荷
    既然Reactor有如此优势,那Spring肯定想纳入己用,于是Spring5推出了自己的响应式编程库Reactive 。参见:Spring官网

    附:

    • Project Reactor是一个运行在JVM上的反应式编程基础库,以“背压”的形式管理数据处理,提供了可组合的异步序列APIFlux和Mono。同时,它也实现了Reactive Streams 规范。
    • Project Reactor主要是由Pivotal公司开发和维护的,Spring框架也是该公司在维护,而且Spring Framework 5中默认使用Reactor作为反应式编程的实现,由此虽然Reactor不是Spring的子项目,也有人称Reactor为Spring Reactor。

    关于Spring 的Reactive

    参考:https://spring.io/reactive

    • Reactor
    Reactive systems have certain characteristics that make them ideal for low-latency, high-throughput workloads. Project Reactor and the Spring portfolio work together to enable developers to build enterprise-grade reactive systems that are responsive, resilient, elastic, and message-driven.

    响应式系统具有某种特性,这些特性使得响应式系统非常适合低延迟、高吞吐量的场景。Project Reactor和Spring portfolio(Spring集)一起工作,使得开发者能够构建响应式的、弹力和消息驱动的企业级响应式系统。

    What is reactive processing? 什么是响应式处理?

    Reactive processing is a paradigm that enables developers build non-blocking, asynchronous applications that can handle back-pressure (flow control).

    响应式处理是一种范例,使开发人员能够构建非阻塞的异步应用程序,可以处理背压(流量控制).

    Why use reactive processing? 为什么要使用响应式处理?

    反应式系统更好地利用了现代处理器。此外,在响应式编程中包含背压可确保解耦组件之间更好的弹性。

    • Project Reactor
    Project Reactor is a fully non-blocking foundation with back-pressure support included. It’s the foundation of the reactive stack in the Spring ecosystem and is featured in projects such as Spring WebFlux, Spring Data, and Spring Cloud Gateway.

    Project Reactor是完全非阻塞的、它也包含了背压(流控制)支持。
    Project Reactro是Spring生态系统中的响应式栈的基础,它在Spring WebFlux、Spring Data以及Spring Cloud Gateway项目中起着重要作用。

    参考:Project Reactor官网

    • Reactive Microservices
    One of the main reasons developers move from blocking to non-blocking code is efficiency. Reactive code does more work with fewer resources. Project Reactor and Spring WebFlux let developers take advantage of multi-core, next-generation processors—handling potentially massive numbers of concurrent connections. With reactive processing, you can satisfy more concurrent users with fewer microservice instances.

    开发者从阻塞编码转向非阻塞编码的一个主要原因是:效率。
    响应式编码(非阻塞)可以用更少的资源做更多的事情。
    Project Reactor和SpringWebFlux允许开发者利用多核心、下一代处理器来处理潜在的海量的并发连接。
    使用响应式处理,用更少的微服务实例就可以满足更多的并发用户。

    • Reactive Microservices With Spring Boot
    The Spring portfolio provides two parallel stacks. One is based on a Servlet API with Spring MVC andSpring Data constructs. The other is a fully reactive stack that takes advantage of Spring WebFlux and Spring Data’s reactive repositories. In both cases, Spring Security has you covered with native support for both stacks.

    Spring集提供了两个并行栈。
    一个是:基于Servlet API,如 SpringMVC和Spring Data的构造。
    另一个是:利用Spring WebFlux和SpringData的响应式仓库的完全响应式栈。

    如何引入Spring Cloud Gateway

    参见官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-starter

    引入依赖spring-cloud-starter-gateway即可。
    两个注意:
    1、因为Spring Cloud Gateway是构建在Spring Boot 2.x, Spring WebFlux,以及Project Reactor上的。这就会导致之前熟悉的同步类库(如:Spring Data和Spring Security)可能不适用了。
    2、Spring Cloud Gateway 需要Spring Boot和Spring Webflux提供的Netty运行环境(jar/依赖包)。因为Spring Coud Gateway项目当在构建成WAR包时,并不能在传统的Servlet容器上运行。

    示例

    pom.xml :只引入了spring-cloud-starter-gateway

    <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.xl.projects</groupId><artifactId>xl-springcloud-parent-pom</artifactId><version>1.0.0</version></parent><artifactId>xl-spring-cloud-gateway-demo001</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency></dependencies></project>

    进入到spring-cloud-starter-gateway中可发现其他需要的依赖,如:netty相关依赖、reactor相关依赖等等。

    主启动类:

    package com.xl.projects.springcloudgateway.demo;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class SpringCloudGatewayDemoApplication {public static void main(String[] args) {SpringApplication.run(SpringCloudGatewayDemoApplication.class, args);}}

    启动:

    成功启动!注意:启动的是Netty,并非Tomcat!

    application.yml

    server:port: 8085spring:application:name: gateway-demo001-servicecloud:gateway:routes:- id: 2023-3-7 09:09:23uri: http://localhost:8080predicates:- Path=/loadb- Method=GET,PUT- Header=header-name-01, header-value-01- Header=header-name-02, header-value-02filters:- AddRequestHeader=X-Request-red, blue- AddRequestParameter=red, blue

    如上配置:

  • 将端口配置为8085;
  • 配置4个断言:
    • 1个Path=/loadb :请求须为localhost:8085/loadb
    • 1个Method=GET,PUT :请求须为 GET或者PUT方式
    • 1个Header : 请求时须加上一个名字为header-name-01,值为header-value-01的header
    • 第2个Header: 请求时须加上一个名字为header-name-02,值为header-value-02的header
      请求同时满足以上4个断言时,就会路由到另一个微服务上去,访问地址为uri+Path(http://localhost8080/loadb)
  • 配置2个过滤器:
    • 增加一个Header: 名称为X-Request-red,值为blue
    • 增加一个请求参数:名称为red, 值为blue

    准备一个微服务端口为8080,以及地址为/loadb的接口。 8080微服务代码:

    package com.xl.module001.controller;import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class TestController {@RequestMapping("/loadb")public String testLoadBalance(HttpServletRequest request,String red) {// 获取参数Enumeration<String> params = request.getParameterNames();String param = params.nextElement();System.out.println("=================param="+param);// 获取请求的HeaderEnumeration<String> headers = request.getHeaderNames();while (headers.hasMoreElements()) {System.out.println("+++++++++++++++++header="+headers.nextElement());}return "module001_8080";}@GetMapping("/netty/loadb")public String test3() {return "this is 8080 netty interface...";}@GetMapping("/")public String test4() {return "this is 8080 root directory";}}

    Filter:

    These are instances of GatewayFilter that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.

    • 这些过滤器是通过指定工厂构建出来的GatewayFilter实例。
    • 可以通过这些过滤器在发送下游请求之前或者之后修改请求和响应。

    官网对应介绍:

    例子:见上面 2 中的 “示例”。

    4 Circuit Breaker integration

    Spring Cloud Gateway 整合熔断降级

    为什么需要熔断降级

    在分布式系统中,网关作为流量的入口,因此会有大量的请求进入网关,向其他服务发起调用,其他服务不可避免的会出现调用失败(超时、异常),失败时不能让请求堆积在网关上,需要快速失败并返回给客户端,想要实现这个要求,就必须在网关上做熔断、降级操作。

    为什么在网关上请求失败需要快速返回给客户端?

    因为当一个客户端请求发生故障的时候,这个请求会一直堆积在网关上,当然只有一个这种请求,网关肯定没有问题(如果一个请求就能造成整个系统瘫痪,那这个系统可以下架了),但是网关上堆积多了就会给网关乃至整个服务都造成巨大的压力,甚至整个服务宕掉。因此要对一些服务和页面进行有策略的降级,以此缓解服务器资源的的压力,以保证核心业务的正常运行,同时也保持了客户和大部分客户的得到正确的相应,所以需要网关上请求失败需要快速返回给客户端。

    • 场景
      网关服务A调用业务服务B时,发现服务B无法调通(比如,断电了等),这时网关服务A就应该直接返回(使用熔断的fallback机制)。

    Spring Cloud专门用于处理熔断降级的网关过滤器工厂: CircuitBreaker的用法

    官网介绍:

    https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-cacherequestbody-gatewayfilter-factory

    1 说明

    The Spring Cloud CircuitBreaker GatewayFilter factory uses the Spring Cloud CircuitBreaker APIs to wrap Gateway routes in a circuit breaker. Spring Cloud CircuitBreaker supports multiple libraries that can be used with Spring Cloud Gateway. Spring Cloud supports Resilience4J out of the box.

    Spring Cloud的熔断API将网关路由包裹成一个熔断器,这就是Spring Cloud CircuitBreaker 网关过滤器工厂的做法。
    Spring Cloud CircuitBreaker支持多个可用于Spring Cloud Gateway的库,其中,Spring Cloud支持对Resilience4J的开箱即用。

    那么Resilience4J是什么?

    • Resilience4j是一个轻量级、易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计。
    • Resilience4j提供高阶函数(decorators)来增强任何功能接口、lambda表达式或方法引用,包括断路器、速率限制器、重试或舱壁。可以在任何函数接口、lambda表达式或方法引用上使用多个装饰器。
    • circuitbreaker组件实现了断路器功能,是基于内存的断路器,采用
      ConcurrentHashMap来实现。
    • There are two starters for the Resilience4J implementations, one for reactive applications and one for non-reactive applications.(有两个Resilience4J 的Spring Cloud Starter实现,一个是响应式的应用,一个是非响应式的应用)—摘自:https://cloud.spring.io/spring-cloud-circuitbreaker/reference/html/spring-cloud-circuitbreaker.html

    org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j- non-reactive applications

    org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j- reactive applications

    下面马上就会用到这个org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j
    所以,可得org.springframework.cloud:spring-cloud-starter-circuitbreaker-reactor-resilience4j是Resilience4J的一种实现

    2 引入熔断器依赖,并简单测试

    To enable the Spring Cloud CircuitBreaker filter, you need to place spring-cloud-starter-circuitbreaker-reactor-resilience4j on the classpath. The following example configures a Spring Cloud CircuitBreaker GatewayFilter:

    spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: https://example.orgfilters:- CircuitBreaker=myCircuitBreaker

    要使用Spring Cloud 熔断过滤器,需要引入依赖:spring-cloud-starter-circuitbreaker-reactor-resilience4j ,然后在application.yml中添加上面的配置即可开始使用:

    pom.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.xl.projects</groupId><artifactId>xl-springcloud-parent-pom</artifactId><version>1.0.0</version></parent><artifactId>xl-spring-cloud-gateway-demo001</artifactId><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId></dependency></dependencies></project>

    application.yml

    server:port: 8085spring:application:name: gateway-demo001-servicecloud:nacos:dicsovery:server-addr: 127.0.0.1:8848username: nacospassword: nacosgateway:discovery:locator:enable: trueroutes:- id: 2023-3-7 09:09:23uri: http://localhost:8080predicates:- Path=/loadb2222- Method=GET,PUT- Header=header-name-01, header-value-01- Header=header-name-02, header-value-02filters:- AddRequestHeader=X-Request-red, blue- AddRequestParameter=red, blue- id: 2023-3-8 08:59:22uri: lb://nacos-providerpredicates:- Path=/netty- id: 2023-3-8 13:27:23uri: http://localhost:8080predicates:- Method=GETfilters:- name: CircuitBreaker #或者配置这样 - CircuitBreaker=myCircuitBreakerargs:name: myCircuitBreaker# fallbackUri: forward:/fallback

    其中,- name: CircuitBreaker 配置中的熔断器名称一定不能错,必须是CircuitBreaker (大小写敏感!)

    演示:

    • 根据yaml文件的配置, uri为http://localhost:8080,如果不启动8080服务那么,就会触发熔断器:以达到检验熔断器是否引入成功
    • 启动本网关服务8085,并发送一个GET请求:

      在yml中注释掉熔断相关的配置,再次测试:


      以上说明,引入熔断器,产生了作用。
    3 添加fallbackuri配置

    The Spring Cloud CircuitBreaker filter can also accept an optional fallbackUri parameter. Currently, only forward: schemed URIs are supported. If the fallback is called, the request is forwarded to the controller matched by the URI. The following example configures such a fallback:

    spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpointfilters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThis- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

    目前fallbackUri中只支持使用forward:来跳转。

    在本网关服务8085中添加一个fallback接口,同样服务8080不启动,以触发熔断机制:

    测试,成功返回“ttt”,说明fallbackUri配置生效:

    4 fallbackUri添加变量

    CircuitBreaker also supports URI variables in the fallbackUri. This allows more complex routing options, like forwarding sections of the original host or url path using PathPattern expression.

    In the example below the call consumingServiceEndpoint/users/1 will be redirected to inCaseOfFailureUseThis/users/1.

    application.yml 配置如下

    spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpoint/{*segments}filters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThis/{segments}

    验证,未成功!!

    5 fallbakcUri可以指向自己服务的一个地址,也可以指向外部服务(通过路由转发)

    The primary scenario is to use the fallbackUri to define an internal controller or handler within the gateway application. However, you can also reroute the request to a controller or handler in an external application, as follows

    application.yml

    spring:cloud:gateway:routes:- id: ingredientsuri: lb://ingredientspredicates:- Path=//ingredients/**filters:- name: CircuitBreakerargs:name: fetchIngredientsfallbackUri: forward:/fallback- id: ingredients-fallbackuri: http://localhost:9994predicates:- Path=/fallback

    测试: localhost:8085/test

    以上,符合预期。

    5 Spring Cloud DiscoveryClient integration

    整合Spring Cloud 服务注册和发现

    参见:2 《Able to match routes on any request attribute.》之 Spring Cloud Gateway中配置负载均衡

    6 Easy to write Predicates and Filters

    易于编写断言和过滤器
    参见:以上内容有如何编写断言和过滤器,除此之外,官方还提供了以下了断言工厂和过滤器工厂:
    参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

    7 Request Rate Limiting

    • TODO

    8 Path Rewriting

    The RewritePath GatewayFilter factory takes a path regexp parameter and a replacement parameter. This uses Java regular expressions for a flexible way to rewrite the request path. The following listing configures a RewritePath GatewayFilter:

    spring:cloud:gateway:routes:- id: rewritepath_routeuri: https://example.orgpredicates:- Path=/red/**filters:- RewritePath=/red/?(?<segment>.*), /$\{segment}

    For a request path of /red/blue, this sets the path to /blue before making the downstream request. Note that the $ should be replaced with $\ because of the YAML specification.
    示例:

    以上都是使用yaml配置文件,也可以使用java代码完成配置

    package com.xl.projects;import java.time.Duration;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.circuitbreaker.resilience4j.ReactiveResilience4JCircuitBreakerFactory;import org.springframework.cloud.circuitbreaker.resilience4j.Resilience4JConfigBuilder;import org.springframework.cloud.client.circuitbreaker.Customizer;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;import org.springframework.cloud.gateway.route.RouteLocator;import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;import org.springframework.context.annotation.Bean;import org.springframework.security.config.web.server.ServerHttpSecurity;import org.springframework.security.core.userdetails.MapReactiveUserDetailsService;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.web.server.SecurityWebFilterChain;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController@SpringBootApplication//@EnableDiscoveryClientpublic class SpringCloudGateApplication {@RequestMapping("/circuitbreakerfallback")public String circuitbreakerfallback() {return "This is a fallback";}@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {//@formatter:offreturn builder.routes().route("path_route", r -> r.path("/get")//.uri("http://httpbin.org")).uri("http://localhost:8089"))//.route("host_route", r -> r.host("*.myhost.org").route("host_route", r -> r.host("localhost:8085").uri("http://127.0.0.1:8080"))//.uri("http://www.baidu.com"))//.uri("http://httpbin.org")) .route("rewrite_route", r -> r.host("localhost:8087") // 不能加http://.filters(f -> f.rewritePath("/foo/(?<segment>.*)","/${segment}")).uri("http://localhost:8080")) // 必须要加上http:////.uri("http://httpbin.org"))//.uri("http://www.baidu.com"))//.filters(f -> f.rewritePath("/foo/(?<segment>.*)",//"/${segment}"))//.uri("http://httpbin.org")).route("circuitbreaker_route", r -> r.host("localhost:8086").filters(f -> f.circuitBreaker(c -> c.setName("slowcmd"))).uri("http://localhost:8079")).route("circuitbreaker_fallback_route", r -> r.host("localhost:8074").filters(f -> f.circuitBreaker(c -> c.setName("slowcmd").setFallbackUri("forward:/fallback"))).uri("http://localhost:8079")).route("limit_route", r -> r.host("localhost:8088").and().path("/anything/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()))).uri("http://httpbin.org")).route("websocket_route", r -> r.path("/echo").uri("ws://localhost:9000")).build();//@formatter:on}@BeanRedisRateLimiter redisRateLimiter() {return new RedisRateLimiter(1, 2);}@BeanSecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {return http.httpBasic().and().csrf().disable().authorizeExchange().pathMatchers("/anything/**").authenticated().anyExchange().permitAll().and().build();}@Beanpublic MapReactiveUserDetailsService reactiveUserDetailsService() {UserDetails user = User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build();return new MapReactiveUserDetailsService(user);}public static void main(String[] args) {SpringApplication.run(SpringCloudGateApplication.class, args);}}

    参考:

    参考:

    • 官网:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
    • https://blog.csdn.net/a1036645146/article/details/106383883
    需要做网站?需要网络推广?欢迎咨询客户经理 13272073477