Spring Cloud Gateway入门与实战

2023-12-28 16:58:53

日升时奋斗,日落时自省?

目录

1、简述

2、网关作用

3、Spring Cloud Gateway组成

4.Spring Cloud Gateway 基础使用

4.1、依赖添加

4.2、设置网关路由规则

5、匹配多个Path

6、更多断言(Predicate)类型

6.1、根据时间匹配

6.2、根据Header匹配

6.3、根据Method匹配

6.4、根据Query匹配

6.5、根据Weight匹配

7、Gateway+Nacos+LoadBalancer

7.1、添加依赖

7.2、设置路由规则

8、过滤器

8.1、概述

8.2、过滤器主要作用

8.3、Spring Cloud Gateway过滤器

8.3.1、内置局部过滤器

AddRequestHeader

AddRequestParameter

PrefixPath

RequestRateLimiter

Retry

8.3.2、内置全局过滤器

8.3.3、自定义全局过滤器

9、原理


1、简述

一个提供统一访问地址的组件的,它充当了客户端和内部微服务之间的中介。

主要负责:

流量路由和转发、将外部请求引导到相应的微服务实例上,同时提供一些功能,如身份认证、授权限流、监控、日志记录等

2、网关作用

路由功能:网关可以根据目标地址的不同,选择最佳的路劲将数据包从源网络路由到目标网络,它通过维护路由表来确定数据包的转发方向,并选择最优的路径

安全控制(统一认证授权):网关可以实施对网络安全策略,对进出的数据包进行检查和过滤。它可以验证和授权来自源网络的数据包,并阻止未经授权的访问。防火墙是一种常见网关设备,用于过滤和保护网络免收恶意攻击和未经授权访问。

协议转换:不同网络使用不同的通信协议,网关可以进行协议转换,使得不同网络的设备可以相互通信,例如的,HTTP协议转换为HTTP协议

网络地址转换(NAT):网关还可以执行网络地址转换,将内部网络使用私有IP地址转换为外部网络使用的公共IP地址,以实现多台计算机共享一个公共IP地址出去上网

3、Spring Cloud Gateway组成

路由(Route):定义了请求应该被转发到哪个目标地址。路由由ID、目标URI、断言和过滤器组成。通过配置多个路由,可以实现不同请求的路由规则

断言(Predicate):用于匹配请求的条件,如果请求匹配断言条件,则会被路由到对应的目标地址。断言可以基于请求的路径、请求头、请求参数等信息进行匹配。

过滤器(Filter):用于在请求路由前或路由后进行一些处理,如添加头部信息、修改请求体等。过滤器可以在全局范围或特定路由范围内匹配,多个过滤器可以组成过滤器链

4.Spring Cloud Gateway 基础使用

Spring Cloud Gateway使用步骤如下:

(1)添加Gateway依赖

(2)设置网关路由规则

4.1、依赖添加

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

4.2、设置网关路由规则

spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: lb://user-service-gateway
          predicates:
            - Path=/user/**

5、匹配多个Path

Spring Cloud Gateway(网关路由规则)中是允许设置多个Path的,只需要在Path中使用英文逗号“,”隔开即可:

spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: lb://user-service-gateway
          predicates:
            - Path=/user/**,/userlog/**

6、更多断言(Predicate)类型

Spring Cloud Gateway支持的断言类型目前有12种,包含以下这些:

(1)根据时间匹配 (包含 3 种类型)

????????a.After: 请求在指定时间之后才匹配

????????b.Before: 请求在指定时间之前才匹配

????????c. Between: 请求在指定时间中间才匹配

(2)Cookie: 配置请求中的 Cookie 值

(3)Header: 配置请求中的 Header 值

(4)Host: 匹配请求头中的 Host 值

(5)Method: 匹配请求头中的 Method 的值

(6)Path: 匹配请求路径

(7)Query: 匹配请求参数

(8)RemoteAddr: 配请求的 IP 地址,支持 IPV4 和 IPV6

(9)Weight: 根据权重来分发请求,权重根据 group 来计算

(10)XForwardedRemoteAddr: 根据 X-Forwarded-For 配

Spring Cloud Gateway 相关内容:Spring Cloud Gateway

针对以上就举几个例子:

6.1、根据时间匹配

Before时间使用 ,在 before的之前的时间都是可以进行路由成功

spring:
  cloud:
    gateway:
      routes:
      - id: before_route    #这个id 是具有唯一性的 
        uri: lb://user-service-gateway    
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

lb 是 "Load Balancer" 的缩写,表示负载均衡的意思,负载均衡到user-service-gateway这个服务实例上

After时间使用 ,在 before的之前的时间都是可以进行路由成功

spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: lb://user-service-gateway    
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

当然还有between就是一个时间返回和时区范围

6.2、根据Header匹配

请求头中需要有网关中能检测到 正则表达式

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

如果请求的头名为 X-Request-Id,且其值符合 \d+ 正则表达式(即其值为一位或多位数字),则该路由与之匹配

其中"X-Request-Id"表示Header中的key,而"\d+"表示的是key的值,并且只能为数字

正则表达式:
(1)\w+:匹配一个或多个字母、数字、下划线字符。

(2)\s+:匹配一个或多个空白字符(包括空格、制表符、换行符等)。

(3).*:匹配任意字符(除了换行符)零次或多次。

(4).+︰匹配除了换行符之外的任意字符一次或多次。

(5) [abc] :匹配字符集中的任意一个字符,例如[abc]可以匹配a、b或c。

(6)[^abc]:匹配除了字符集中的任意字符之外的任意字符,例如[^abc]可以匹配除了a、 b和c之外的任意字符。

(7)^:匹配字符串的开始位置。

(8)$:匹配字符串的结束位置。

(9)|:表示"或"的意思,用于匹配多个模式中的任意一个。

(10)():用于分组,可以将一组字符作为一个整体进行匹配。

6.3、根据Method匹配

spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

注意:方法必须是大写;

允许多个请求类型,用逗号隔开

6.4、根据Query匹配

Query就是路由的时候带的参数,指定带参才能访问

spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=uid,\d+

逗号后面的 是一个正则表达式,更加精确的指定访问

6.5、根据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

注意:Weight相较于前面的内容较为特殊,实例可能是在不同分组(Nacos有一个分组结合使用),group1就是组名,逗号后面的数字就是权重(int类型)

7、Gateway+Nacos+LoadBalancer

7.1、添加依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>        
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

7.2、设置路由规则

配置路由实例,这个实例也是不需要配置到注册中心的

spring:
  application:
    name: service-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        username: nacos
        password: nacos
        register-enabled: false   #取消注册实例
    gateway:
      routes:
        - id: userservice
          uri: lb://user-service-gateway
          predicates:
            - Path=/user/**,/userlog/**

注意:Spring Cloud Gateway 中的服务名不要使用下划线“_”的命名方式,某些版本会识别此类服务名

8、过滤器

8.1、概述

过滤器通常用户拦截,处理或修改数据流或者事件流,在数据流中执行特定的操作或转换

8.2、过滤器主要作用

功能扩展和定制:过滤器可以用于对现有功能进行扩展和定制。通过拦截和处理数据流或事件流,可以修改数据,增加额外的功能逻辑,实现特定的业务需求。例如,可以使用过滤器在请求之前进行身份验证.权限控制,或者在响应之后进行日志记录、数据转换等操作。

数据校验和过滤:过滤器可以用于对数据进行校验和过滤。在接收到数据之后,可以使用过滤器对数据进行检查,验证数据的合法性,过滤掉无效或不符合要求的数据。这有助于保证数据的准确性、完整性和安全性。

安全保护:过滤器可以用于提供安全保护措施。可以使用过滤器对输入的请求进行检查和清洗,以防止潜在的安全漏洞,例如跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等攻击。过滤器还可以进行访问控制,验证权限和实施安全策略。

性能优化:过滤器可以用于性能优化。例如,在数据处理流水线中,可以使用过滤器对数据进行转换、过滤或缓存,以提高处理速度和效率。过滤器还可以用于数据压缩、缓存预热等场景,减少数据传输和处理的成本。

统一处理和逻辑复用:过滤器提供了一种统一的处理方式,可以在不同的组件或模块上应用相同的逻辑或处理方式。通过将处理逻辑抽象为过滤器,可以避免重复代码、统一错误处理和异常处理等,提高代码的复用性和可维护性。

8.3、Spring Cloud Gateway过滤器

在Spring Cloud Gateway中包含以下两种过滤器:

(1)内置过滤器:内置局部过滤器、内置全局过滤器

(2)自定义过滤器

8.3.1、内置局部过滤器

AddRequestHeader

给后续请求的接口添加Header信息,如下配置所示

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

filters就是过滤器的配置项,其中AddRequestHeader表示的添加返回头过滤器,前面的值“X-Request-red”为key,后面的“blue”为value

GatewayFilter Factory中有30多种的过滤器的种类,官方文档:

Spring Cloud Gateway

AddRequestParameter

给后续请求的接口添加请求信息,如下配置所以

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

类型基本如:url?flag=blue才能通过过滤器

PrefixPath

在请求的url前面添加前缀,例如请求的是/user路径为开头,但是添加了PrefixPath为/new,那么访问得地址就变为了"/new/user",配置如下:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/new
RequestRateLimiter

网关限流过滤器,Spring Cloud Gateway内置了限流功能,它使用的限流算法是令牌桶的限流算法

令牌桶限流算法:和网络传输的那个令牌是一样的,令牌是以一定速率进行放入令牌桶内的,外面从令牌桶中取出令牌,只要令牌桶里有令牌你请求多少用于多少我都能接收,每次请求都是要消耗掉一个令牌的,如果桶内没有令牌了,那就请求失败

Spring Cloud Gateway当前版本支持和Redis一起实现限流功能的,它的实现步骤总共分为以下三步:

①添加Redis框架依赖

②创建限流规则

③配置限流过滤器

添加Redis框架依赖

官网是提供了相关依赖概述

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

创建限流规则

新建一个类,接下来实现一下根据IP进行限流,实现代码如下:

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class IpAddressKeyResolver implements KeyResolver {
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        return Mono.just(exchange.getRequest().getRemoteAddress().getHostString());
    }
}

注:这个类单独写出来Component注入到Spring中

配置限流规则

在项目的配置文件中,配置以下内容:

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 10
            redis-rate-limiter.burstCapacity: 20
            key-resolver: "#{@IpAddressKeyResolver }"  #采用的是spEL表达式
  data:
    redis:
       host: 127.0.0.1
       port: 16379
       database: 0

其中,name必须等于 "RequestRateLimiter"内置限流过滤器,其他的参数含义如下:

redis-rate-limiter.replenishRate:令牌填充速度:每秒允许请求数

redis-rate-limiter.burstCapacity: 令牌桶容量:最大令牌数

KeyResolver: 根据那个key进行限流,它的值是spEL表达式

key-resolver: "#{@IpAddressKeyResolver}" 表示使用名为 IpAddressKeyResolver?(前面写类)的 Bean 来解析限流规则中的 Key。具体来说,IpAddressKeyResolver 是自定义的 Key 解析器,通过解析请求的 IP 地址来生成 Key。这样,在限流过滤器中使用该 Key 解析器,就可以根据请求的 IP 地址进行限流

注意:Spring Cloud Gateway配合Redis实现限流的时候,它对于Redis的版本是有要求的,因为它在限流调用了一个Redis高版本的函数,所以Redis Server版本太低,限流无效,Redis Server 最好是5.x版本以上的

Retry

请求重试过滤器配置,具体案例如下:

spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: lb://user-service-gateway
          predicates:
            - Path=/user/**,/userlog/**
          filters:
            - name: Retry
              args:
                retries: 3
                statuses: GATEWAY_TIMEOUT
                method: GET
                series: SERVER_ERROR
                backoff:
                  firstBackoff: 10ms
                  maxBackoff: 50ms
                  factor: 2
                  basedOnPreviousValue: false

注意:重试过滤器的name一定要等于“Retry”,因为“Retry”就是内置重试过滤器的名字,改为其他的框架就识别不到了

其中:

retries:重试次数

statuses:重试的HTTP状态码,取值参考: 在idea中shift+shift进行搜索HttpStatus

org.springframework.http.HttpStatus ,状态码匹配上才会重试

?methods:重试的HTTP方法,方法类型匹配上才会重试,取值GET,来自于org.springframework.http.HttpMethod 中的方法

series:状态码配置(分段),符合的某段状态码才会进行重试逻辑,默认值是SERVER_ERROR,值是5,就是5XX开头的状态码,共有5个值 分别就是五种状态码

backoff:重试指数配置策略,默认关闭

firstBackoff :第一次重试间隔

maxBackoff:最大重试间隔

factor:n代指重试系数? ?重试的间隔时间=firstBackoff * (factor^n) 计算时间间隔

basedOnPreviousValue:? false 表示基于上次重试的时间加上重试系数来计算

如果为true的话,则使用prevBackoff*factor计算重试

8.3.2、内置全局过滤器

使用default-filters配置的就是全局过滤器

全局过滤器是可以和局部过滤器一起存在的

  1. 首先会执行全局过滤器。
  2. 然后执行与特定路由匹配的局部过滤器。
spring:
  cloud:
    gateway:
      routes:
        - id: userservice
          uri: lb://user-service-gateway
          predicates:
            - Path=/user/**,/userlog/**
      default-filters:
        - name: Retry
          args:
            retries: 3
            statuses: GATEWAY_TIMEOUT
            method: GET
            series: SERVER_ERROR
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false

8.3.3、自定义全局过滤器

我们可以使用Spring Cloud Gateway 提供的全局过滤器来实现统一认证授权,例如以下操作:

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.lang.annotation.Annotation;

@Component
public class AuthFilter implements GlobalFilter, Order {
    // exchange 代表的是执行事件  chain 网管过滤器链
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //未登录判断逻辑 当参数中如果 username=admin && password = admin
        //继续执行 、否则退出执行
        //获取request
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String username = request.getQueryParams().getFirst("username");
        String password = request.getQueryParams().getFirst("password");
        //进行过滤条件判断
        if(username!=null&&username.equals("admin")
                &&password!=null&&password.equals("admin")){
            //如果判断成功, 就继续按调用链执行
            return chain.filter(exchange);
        }else{
            //给响应设置一个状态表示当前出现的问题
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            //执行完成不用再去执行下面的内容了
            return response.setComplete();
        }
    }

    //设置当前过滤器的执行顺序 值越大 越早触发
    @Override
    public int value() {
        //越小 调用的越早
        return 1;
    }

    @Override
    public Class<? extends Annotation> annotationType() {
        return null;
    }
}

9、原理

Spring Cloud Gateway工作原理:

客户端向 Spring Cloud Gateway 发出请求。如果网关处理程序映射确定请求与路由相匹配,则会将其发送到网关 Web 处理程序。该处理程序通过特定于请求的过滤链运行请求。之所以用虚线划分过滤器,是因为过滤器可以在代理请求发送之前和之后运行逻辑。所有 "前 "过滤逻辑都已执行。然后发出代理请求。代理请求发出后,运行 "后 "过滤逻辑。

文章来源:https://blog.csdn.net/c_study__c/article/details/135123966
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。