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

Spring Cloud框架学习-Spring Cloud Gateway

ztj100 2024-10-29 18:19 19 浏览 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"));
}

相关推荐

从IDEA开始,迈进GO语言之门(idea got)

前言笔者在学习GO语言编程的时候,GO语言在国内还没有像JAVA/Php/Python那样普及,绕了不少的弯路,要开始入门学习一门编程语言,最好就先从选择一个好的编程语言的开发环境开始,有了这个开发环...

基于SpringBoot+MyBatis的私人影院java网上购票jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于SpringBoot...

基于springboot的个人服装管理系统java网上商城jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...

基于springboot的美食网站Java食品销售jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍基于springboot...

贸易管理进销存springboot云管货管账分析java jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目描述贸易管理进销存spring...

SpringBoot+VUE员工信息管理系统Java人员管理jsp源代码Mysql

本项目为前几天收费帮学妹做的一个项目,JavaEEJSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。一、项目介绍SpringBoot+V...

目前见过最牛的一个SpringBoot商城项目(附源码)还有人没用过吗

帮粉丝找了一个基于SpringBoot的天猫商城项目,快速部署运行,所用技术:MySQL,Druid,Log4j2,Maven,Echarts,Bootstrap...免费给大家分享出来前台演示...

SpringBoot+Mysql实现的手机商城附带源码演示导入视频

今天为大家带来的是基于SpringBoot+JPA+Thymeleaf框架的手机商城管理系统,商城系统分为前台和后台、前台用的是Bootstrap框架后台用的是SpringBoot+JPA都是现在主...

全网首发!马士兵内部共享—1658页《Java面试突击核心讲》

又是一年一度的“金九银十”秋招大热门,为助力广大程序员朋友“面试造火箭”,小编今天给大家分享的便是这份马士兵内部的面试神技——1658页《Java面试突击核心讲》!...

SpringBoot数据库操作的应用(springboot与数据库交互)

1.JDBC+HikariDataSource...

SpringBoot 整合 Flink 实时同步 MySQL

1、需求在Flink发布SpringBoot打包的jar包能够实时同步MySQL表,做到原表进行新增、修改、删除的时候目标表都能对应同步。...

SpringBoot + Mybatis + Shiro + mysql + redis智能平台源码分享

后端技术栈基于SpringBoot+Mybatis+Shiro+mysql+redis构建的智慧云智能教育平台基于数据驱动视图的理念封装element-ui,即使没有vue的使...

Springboot+Mysql舞蹈课程在线预约系统源码附带视频运行教程

今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的Springboot+Mysql舞蹈课程在线预约系统,系统项目源代码在【猿来入此】获取!https://www.yuan...

SpringBoot+Mysql在线众筹系统源码+讲解视频+开发文档(参考论文

今天发布的是由【猿来入此】的优秀学员独立做的一个基于springboot脚手架的在线众筹管理系统,主要实现了普通用户在线参与众筹基本操作流程的全部功能,系统分普通用户、超级管理员等角色,除基础脚手架外...

Docker一键部署 SpringBoot 应用的方法,贼快贼好用

这两天发现个Gradle插件,支持一键打包、推送Docker镜像。今天我们来讲讲这个插件,希望对大家有所帮助!GradleDockerPlugin简介...

取消回复欢迎 发表评论: