百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Spring Cloud框架学习-Spring Cloud Gateway

ztj100 2024-10-29 18:19 23 浏览 0 评论

1. 简介

Spring Cloud Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等。

Spring Cloud Gateway 具有如下特性:

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

Spring Cloud Gateway的重要的三大概念:

  • Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由;
  • Predicate(断言):指的是Java 8 的 Function Predicate。输入类型是Spring框架中的ServerWebExchange。这使开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数。如果请求与断言相匹配,则进行路由;
  • Filter(过滤器):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前后对请求进行修改。

Spring Cloud Gateway工作原理示例图:

客户端向 Spring Cloud Gateway 发出请求,如果请求与网关程序定义的路由匹配,则该请求就会被发送到网关 Web 处理程序,此时处理程序运行特定的请求过滤器链。

过滤器之间用虚线分开的原因是过滤器可能会在发送代理请求的之前和之后执行逻辑。所有 pre 过滤器逻辑先执行,然后执行代理请求;代理请求完成后,再执行任务 post 过滤器逻辑。

和Zuul的对比:

  1. Zuul 是 Netflix 公司的开源项目,Spring Cloud Gateway 是 Spring 家族中的产品,可以和Spring 家族中的其他组件更好地融合。
  2. Zuul 1.x基于Servlet 2. 5使用阻塞架构,使用的是阻塞式的 API,不支持长连接,例如Websocket。
  3. Spring Cloud Gateway 支持限流。
  4. Spring Cloud Gateway 基于 Netty 来开发,实现了异步和非阻塞,占用资源更小,性能强于Zuul。

2. 基本用法

Spring Cloud Gateway 支持两种不同的配置路由的方式:编码式和yml文件配置

2.1 编码式配置路由

创建Spring Boot项目,添加Spring Cloud Gateway依赖:

<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-hateoas</artifactId>
				</exclusion>
			</exclusions>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

项目创建后,通过配置RouteLocator实现请求转发

@SpringBootApplication
public class DemoApplication {
 

	public static void main(String[] args) {
 
		SpringApplication.run(DemoApplication.class, args);
	}

	@Bean
    RouteLocator routeLocator(RouteLocatorBuilder builder){
 
        return  builder.routes().route("test_route", r -> r.path("/get").uri("http://httpbin.org")).build();
    }
}

配置完成后,重启项目,请求http://localhost:8080/get

2.2 配置文件配置路由

对应properties配置示例

spring.cloud.gateway.routes[0].id=test_route
spring.cloud.gateway.routes[0].uri=http://httpbin.org
spring.cloud.gateway.routes[0].predicates[0]=Path=/get

对应YML配置示例

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
        uri: http://httpbin.org
        predicates:
          - Path=/get

2.3 服务化配置

在Gateway项目上添加依赖,注册Gateway到Eureka上。

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>

配置文件中添加注册中心配置,并开启自动代理

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Path=/get
      discovery:
        locator:
          enabled: true # 开启自动代理
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1111/eureka
logging:
  level:
    org.springframework.cloud.gateway: debug

启动Eureka服务,启动Gateway和provider(服务提供者)服务,注册Gateway和provider服务到Eureka注册中心上。

provider服务的端口号为1113,Gateway的端口为8080.下面通过Gateway访问provider服务的hello接口

3. Predicate断言

Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。Spring Cloud Gateway包括许多内置的Route Predicate工厂( 包括时间匹配,请求方式匹配,请求路径匹配,参数匹配等)。所有这些Predicate都与HTTP请求的不同属性匹配。多个Route Predicate工厂可以进行组合,下面我们来介绍一些常用的Route Predicate。

3.1 时间匹配

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - After=2021-01-01T01:01:01+08:00[Asia/Shanghai]

表示请求时间在 2021-01-01T01:01:01+08:00[Asia/Shanghai] 时间之后才会被路由。

除了 After 之外,还有两个关键字:

  • Before,表示在某个时间点之前的请求匹配到该路由
  • Between,表示在两个时间点之间的请求匹配到该路由,两个时间点用 , 隔开

3.2 请求方式匹配

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Method=GET

配置表示只给GET请求路由

3.3 请求路径匹配

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Path=/2019/0612/{
 segment}

表示路径满足 /2019/0612/ 这个规则,都会被进行转发

3.4 参数匹配

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Query=name

表示请求中一定要有 name 参数才会进行转发,否则不会进行转发,也可以指定参数和参数的值。

例如参数的key为name,value必须要以java开始:

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Query=name,java.*

上面多种匹配方式也可以组合使用

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Query=name,java.*
            - Path=/2019/0612/{
 segment}
            - Method=GET

3.5 Cookie匹配

带有指定Cookie的请求会匹配该路由。

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Cookie=username

3.6 请求头Header匹配

带有指定Cookie的请求会匹配该路由。如下带有请求头为"X-Request-Id:test123"的请求可以匹配该路由。

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Header=X-Request-Id

3.7 Host主机匹配

带有指定Host的请求会匹配该路由。如下带有Host:www.baidu.com的请求会匹配到该路由

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - Host=www.**.com

3.8 远程地址RemoteAddr匹配

从指定远程地址发起的请求可以匹配该路由。

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: http://httpbin.org
          predicates:
            - RemoteAddr=192.168.1.1/24

3.8 权重匹配

使用权重来路由相应请求,以下表示有80%的请求会被路由到localhost:8201,20%会被路由到localhost:8202。

spring:
  cloud:
    gateway:
      routes:
      - id:weight_high
        uri:http://localhost:8201
        predicates:
        - Weight=group1,8
      - id: weight_low
        uri: http://localhost:8202
        predicates:
        - Weight=group1,2

4. Filter过滤器

Spring Cloud Gateway中的过滤器分为两大类:全局过滤器GlobalFilter和路由过滤器RouteFilter。下面介绍常用的几个过滤器。

4.1 AddRequestParameter GatewayFilter

使用AddRequestParameter过滤器,给/test_get请求自动额外添加参数

spring:
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: lb://provider
          filters:
            - AddRequestParameter=name,robot
          predicates:
            - Path=/test_get

uri: lb://provider的作用是开启负载均衡功能,provider服务提供接口/test_get

浏览器请求Gateway,实现转发到provider的test_get接口,并自动添加上参数。

请求test_get接口,已有参数的话会额外加上过滤器配置的参数。

4.2 StripPrefix GatewayFilter

StripPrefix GatewayFilter是对指定数量的路径前缀进行去除的过滤器。

spring:
  cloud:
    gateway:
      routes:
      - id: test_route
        uri: http://localhost:8201
        predicates:
        - Path=/user-service/**
        filters:
        - StripPrefix=2

StripPrefix=2配置会把以/user-service/开头的请求的路径去除两位,即请求

http://localhost:9201/user-service/a/user/1

相当于请求该地址:

http://localhost:8201/user/1

4.3 PrefixPath GatewayFilter

PrefixPath GatewayFilter会对原有路径进行增加操作的过滤器。

spring:
  cloud:
    gateway:
      routes:
      - id: test_route
        uri: http://localhost:8201
        predicates:
        - Path=/user-service/**
        filters:
        - PrefixPath=/user

配置请求前缀为/user-service/的请求添加/user路径前缀,即请求

http://localhost:9201/user-service/1

相当于请求该地址:

http://localhost:8201/user-service/user/1

4.4 Hystrix GatewayFilter

Hystrix 过滤器允许我们将断路器功能添加到网关路由中,使服务免受级联故障的影响,并提供服务降级处理。

首先在pom.xml中添加Hystrix的相关依赖,开启断路器功能

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

添加相关服务降级的处理类

@RestController
public class FallbackController {
 


    @GetMapping("/fallback")
    public Object fallback() {
 
        Map<String,Object> result = new HashMap<>();
        result.put("data",null);
        result.put("message","get request fallback!");
        result.put("code",500);
        return result;
    }
}

在配置文件中添加相关配置:当路由出错时会转发到服务降级处理的控制器上。

spring:
  cloud:
    gateway:
      routes:
        - id: hystrix_route
          uri: http://localhost:8201
          predicates:
            - Method=GET
          filters:
            - name: Hystrix
              args:
                name: fallback
                fallbackUri: forward:/fallback

请求http://localhost:8080/1发现已经返回了服务降级的处理信息,因为http://localhost:8201/没有提供该接口。

4.5 RequestRateLimiter GatewayFilter

RequestRateLimiter 过滤器可以用于限流,使用RateLimiter实现来确定是否允许当前请求继续进行,如果请求太频繁默认会返回HTTP 429 - Too Many Requests响应。

在pom.xml中添加相关依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

添加限流策略的配置类,提供策略ipKeyResolver根据访问IP进行限流。

@Configuration
public class RedisRateLimiterConfig {
 

    @Bean
    public KeyResolver ipKeyResolver() {
 
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
}

在yml配置文件中添加Redis和RequestRateLimiter的配置,这里配置对所有的GET请求都进行了按IP来限流的操作。

spring:
  redis:
    host: localhost
    password: 123
    port: 6379
  cloud:
    gateway:
      routes:
        - id: test_route
          uri: lb://provider
          filters:
            - AddRequestParameter=name,robot
          predicates:
            - Path=/test_get
        - id: hystrix_route
          uri: http://localhost:8201
          predicates:
            - Method=GET
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                fallbackUri: forward:/fallback
        - id: requestratelimiter_route
          uri: http://localhost:1113
          predicates:
            - Method=GET
          filters:
            - name: RequestRateLimiter
              args:
                #每秒允许处理的请求数量
                redis-rate-limiter.replenishRate: 1
                #每秒最大处理的请求数量
                redis-rate-limiter.burstCapacity: 2
                #限流策略,对应策略的Bean
                key-resolver: "#{@ipKeyResolver}"

      discovery:
        locator:
          enabled: true # 开启自动代理
  application:
    name: gateway
eureka:
  client:
    service-url:
      defaultZone: http://localhost:1111/eureka
logging:
  level:
    org.springframework.cloud.gateway: debug

``

RequestRateLimiter使用的算法是令牌桶算法,令牌桶算法介绍

令牌桶算法

RequestRateLimiter的配置说明:

  • filter名称必须是“RequestRateLimiter”
  • redis-rate-limiter.replenishRate:允许用户每秒处理多少个请求。这是令牌桶的填充速率。
  • redis-rate-limiter.burstCapacity:令牌桶的容量,允许在一秒钟内完成的最大请求数。这是令牌桶可以保存的令牌数。
  • redis-rate-limiter.requestedTokens: 是每个请求消耗多少个令牌,默认是1。
  • key-resolver:使用SpEL表达式按名称引用bean。

下面进行测试,启动provider服务,注册到注册中心http://localhost:1111/eureka上,提供hello接口。频繁多次浏览器访问:http://localhost:8080/hello ,会返回状态码为429的错误;

查看Redis中的Key:

  • 大括号中就是限流Key,这里我们测试的是ip限流,所以key是IP,本地访问的就是0:0:0:0:0:0:0:1/
  • timestamp:存储的是当前时间的秒数,也就是System.currentTimeMillis() / 1000或者Instant.now().getEpochSecond()
  • tokens:存储的是当前这秒钟的对应的可用的令牌数量

我们不仅可以通过ip进行限流,还可以根据ServerHttpRequest的其他参数进行限流

例如根据请求参数中的username进行限流

@Bean
KeyResolver userKeyResolver() {
 
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

相关推荐

如何将数据仓库迁移到阿里云 AnalyticDB for PostgreSQL

阿里云AnalyticDBforPostgreSQL(以下简称ADBPG,即原HybridDBforPostgreSQL)为基于PostgreSQL内核的MPP架构的实时数据仓库服务,可以...

Python数据分析:探索性分析

写在前面如果你忘记了前面的文章,可以看看加深印象:Python数据处理...

CSP-J/S冲奖第21天:插入排序

...

C++基础语法梳理:算法丨十大排序算法(二)

本期是C++基础语法分享的第十六节,今天给大家来梳理一下十大排序算法后五个!归并排序...

C 语言的标准库有哪些

C语言的标准库并不是一个单一的实体,而是由一系列头文件(headerfiles)组成的集合。每个头文件声明了一组相关的函数、宏、类型和常量。程序员通过在代码中使用#include<...

[深度学习] ncnn安装和调用基础教程

1介绍ncnn是腾讯开发的一个为手机端极致优化的高性能神经网络前向计算框架,无第三方依赖,跨平台,但是通常都需要protobuf和opencv。ncnn目前已在腾讯多款应用中使用,如QQ,Qzon...

用rust实现经典的冒泡排序和快速排序

1.假设待排序数组如下letmutarr=[5,3,8,4,2,7,1];...

ncnn+PPYOLOv2首次结合!全网最详细代码解读来了

编辑:好困LRS【新智元导读】今天给大家安利一个宝藏仓库miemiedetection,该仓库集合了PPYOLO、PPYOLOv2、PPYOLOE三个算法pytorch实现三合一,其中的PPYOL...

C++特性使用建议

1.引用参数使用引用替代指针且所有不变的引用参数必须加上const。在C语言中,如果函数需要修改变量的值,参数必须为指针,如...

Qt4/5升级到Qt6吐血经验总结V202308

00:直观总结增加了很多轮子,同时原有模块拆分的也更细致,估计为了方便拓展个管理。把一些过度封装的东西移除了(比如同样的功能有多个函数),保证了只有一个函数执行该功能。把一些Qt5中兼容Qt4的方法废...

到底什么是C++11新特性,请看下文

C++11是一个比较大的更新,引入了很多新特性,以下是对这些特性的详细解释,帮助您快速理解C++11的内容1.自动类型推导(auto和decltype)...

掌握C++11这些特性,代码简洁性、安全性和性能轻松跃升!

C++11(又称C++0x)是C++编程语言的一次重大更新,引入了许多新特性,显著提升了代码简洁性、安全性和性能。以下是主要特性的分类介绍及示例:一、核心语言特性1.自动类型推导(auto)编译器自...

经典算法——凸包算法

凸包算法(ConvexHull)一、概念与问题描述凸包是指在平面上给定一组点,找到包含这些点的最小面积或最小周长的凸多边形。这个多边形没有任何内凹部分,即从一个多边形内的任意一点画一条线到多边形边界...

一起学习c++11——c++11中的新增的容器

c++11新增的容器1:array当时的初衷是希望提供一个在栈上分配的,定长数组,而且可以使用stl中的模板算法。array的用法如下:#include<string>#includ...

C++ 编程中的一些最佳实践

1.遵循代码简洁原则尽量避免冗余代码,通过模块化设计、清晰的命名和良好的结构,让代码更易于阅读和维护...

取消回复欢迎 发表评论: