首页 > 其他分享 >Spring Cloud Gateway简单使用

Spring Cloud Gateway简单使用

时间:2023-06-13 14:35:08浏览次数:47  
标签:exchange Spring springframework 路由 Cloud import org Gateway cloud



文章目录

  • 一、简介
  • 1、功能特点:
  • 2、术语解释
  • 3、网关技术
  • 二、快速开始
  • 1、创建Spring boot工程
  • 2、启动引导类开启注册中心Eureka客户端发现
  • 3、配置文件`appliation.yml`
  • 4、编写路由规则
  • 三、路由配置(转发)(predicates)
  • 1、Query属性
  • 2、Header
  • 3、Method
  • 4、RemoteAddr
  • 5、Host
  • 6、Cookie
  • 7、Before
  • 8、After
  • 9、Between
  • 10、Weight
  • 四、过滤器(拦截)(Filter)
  • 1、简介
  • 2、系统内置过滤器使用
  • 2.1 添加响应头(AddResponseHeader)
  • 2.2 增加路由配置(PrefixPath)
  • 2.3 删除路由配置(StripPrefix)
  • 2.4 AddRequestHeader
  • 2.5 AddRequestParameter
  • 2.6 DedupeResponseHeader
  • 2.7 CircuitBreaker
  • 2.8 FallbackHeaders
  • 2.9 RequestRateLimiter
  • 2.10 RedirectTo
  • 2.11 RemoveRequestHeader
  • 2.12 RemoveResponseHeader
  • 2.13 RemoveRequestParameter
  • 2.14 RewritePath
  • 2.15 RewriteResponseHeader
  • 2.16 SaveSession
  • 2.17 SecureHeaders
  • 2.18 Retry
  • 2.19 RequestSize
  • 2.20 ModifyRequestBody
  • 2.21 ModifyResponseBody
  • 2.22 SetPath
  • 2.23 SetRequestHeader
  • 2.24 SetResponseHeader
  • 2.25 SetStatus
  • 3、自定义全局过滤器
  • 3.1 假如token为null,则拦截
  • 3.2 IP过滤器
  • 3.3 请求url过滤器
  • 4、自定义可配置过滤器(添加到配置文建)
  • 五、其它配置
  • 1、网关自动映射处理
  • 2、动态路由
  • 3、跨域配置
  • 4、记录执行耗时
  • 5、`exchange`代码信息
  • 六、网关限流
  • 1、简介
  • 2、令牌桶算法简介
  • 3、代码实现
  • 3.1 `pom.xml`依赖
  • 3.2 定义KeyResolver
  • 3.3 修改配置
  • 3.4 最终配置:



一、简介

Gateway网关是我们服务的守门神,所有微服务的统一入口。Spring Cloud Gateway 是 Spring Cloud的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。在Gateway之前,SpringCloud并不自己开发网关,可能是觉得Netflflix公司的Zuul不行吧,然后自己就写了一个,也是替代Netflflix Zuul。其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

本身也是一个微服务,需要注册到Eureka。

官网:

https://spring.io/projects/spring-cloud-gateway

1、功能特点:

  • 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
  • 动态路由
  • Predicates 和 Filters 作用于特定路由
  • 集成 Hystrix 断路器
  • 集成 Spring Cloud DiscoveryClient
  • 简单好用的 Predicates 和 Filters
  • 限流
  • 路径重写

Spring Cloud Gateway简单使用_spring

  • 不管是来自客户端的请求,还是服务内部调用。一切对服务的请求都可经过网关。
  • 网关实现鉴权、动态路由等等操作。
  • Gateway是我们服务的统一入口。
  • 鉴权,安全控制,⽇志统⼀处理,易于监控的相关功能。

2、术语解释

Route(路由):这是网关的基本模块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。

Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。

Filter(过滤器):这是org.springframework.cloud.gateway.fifilter.GatewayFilter的实例,我们可以使用它修改请求和响应。

3、网关技术

  • nginx Nginx (engine x) :是⼀个⾼性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。
  • zuul :是 Netflix 出品的⼀个基于 JVM 路由和服务端的负载均衡器。
  • spring-cloud-gateway: 是spring 出品的 基于spring 的⽹关项⽬,集成断路器,路径重写,性能⽐Zuul好。

二、快速开始

1、创建Spring boot工程


Spring Cloud Gateway简单使用_spring cloud_02

2、启动引导类开启注册中心Eureka客户端发现

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient // 开启Eureka客户端发现服务
public class DemoGatewayApplication {

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

3、配置文件appliation.yml

# 端口号
server.port: 10010
# 应用名
spring.application.name: api-gateway
# 注册中心地址
eureka.client.service-url.defaultZone: http://8.131.239.157:10086/eureka/

4、编写路由规则

spring:
  cloud:
    gateway:
    # 路由si(集合)
      routes:
      	# id(唯一标识)
        - id: websocket_test
        # 路由服务地址(转发后地址)
          uri: http://127.0.0.1:9091
          order: 9000
        # 断言(判断哪些请求要被转发)
          predicates:
            - Path=/user/**
  • 将符合 path 规则的请求,路由到 uri 参数指定地址。
  • 举例http://localhost:10010/user/fifindById?id=1 路由转发到http://localhost:9091/user/fifindById?id=1
  • 访问路径中,必须包含路由规则的映射路径/user才会被路由

三、路由配置(转发)(predicates)

谓词(predicates):当满足条件在进行路由转发

在 Spring Cloud Gateway 中谓词实现 GatewayPredicate 接口。其中类名符合: XXXRoutepredicateFactory,其中 XXX 就是在配置文件中谓词名称。在上面示例中 Path=/demo/** 实际上使用的就是PathRoutePredicateFactory


Spring Cloud Gateway简单使用_bc_03

所有的谓词都设置在 predicates 属性中,当设置多个谓词时取逻辑与条件,且一个谓 词只能设置一组条件,如果需要有个多条件,添加多个相同谓词。

1、Query属性

表示路径满足/system/**同时包含参数 abc。

predicates:
  - Path=/system/**
  - Query=abc

支持正则表达式jqk.

支持指定某个字段值abc,jqk.

abc=jqka 或 abc=jqkw 能满足谓词条件。

predicates:
  - Path=/system/**
  - Query=abc,jqk.

测试:

http://localhost:9000/system/one?abc=jqk

完整版:

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
        filters:
          - StripPrefix= 1

2、Header

表示请求头中必须包含的内容。

  • 参数名和参数值之间依然使用逗号。
  • 参数值要使用正则表达式。
  • 支持选择多个Header头信息。

如果 Header 只有一个值表示请求头中必须包含的参数。如果有两个值,第一个表示请求头必须包含的参数名,第二个表示请求头参数对应值。

predicates:
  - Header=Connection,keep-alive
  - Header=Cache-Control,max-age=0

完整版:

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0

3、Method

Method 表示请求方式。支持多个值,使用逗号分隔,多个值之间为 or 条件。

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST

4、RemoteAddr

允许访问的客户端地址

  • 要使用127.0.0.1,不要使用localhost。
spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1

5、Host

匹配请求中的Host信息。满足Ant模式。

?:匹配一个字符

*:匹配0个或多个字符

**:匹配0个或多个目录

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1
          - Host=127.0.0.1:9000

6、Cookie

要求请求中包含指定的Cookie名和满足特定正则要求的值。

  • 必须要有2个值,第一个包含的是参数名,第2个表示参数对应的值(正则表达式)。
spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1
          - Host=127.0.0.1:9000
          - Cookie=age,.*

7、Before

在指定时间点之前

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1
          - Host=127.0.0.1:9000
          - Cookie=age,.*
          - Before=2020-01-31T18:00:00.000+08:00[Asia/Shanghai]

8、After

在指定时间点之后

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1
          - Host=127.0.0.1:9000
          - Cookie=age,.*
          - Before=2020-01-31T18:00:00.000+08:00[Asia/Shanghai]
          - After=2020-01-31T18:00:00.000+08:00[Asia/Shanghai]

9、Between

必须在设定的范围时间内,才能进行路由转发

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
          - Query=abc
          - Header=Connection,keep-alive
          - Header=Cache-Control,max-age=0
          - Method=GET,POST
          - RemoteAddr=127.0.0.1
          - Host=127.0.0.1:9000
          - Cookie=age,.*
          - Before=2020-01-31T18:00:00.000+08:00[Asia/Shanghai]
          - After=2020-01-31T18:00:00.000+08:00[Asia/Shanghai]
          - Between=2020-01-31T18:00:00.000+08:00[Asia/Shanghai], 2020-02-01T00:00:00.000+08:00[Asia/Shanghai]

10、Weight

设置服务转发的权重,用于限制某个的请求占比

语法:Weight=组名,负载均衡权重

suiyi:权重:20%

suiyi2:权重:80%

spring:
  cloud:
    routes:
      - id: suiyi
        uri: lb://demo-one
        predicates:
          - Path=/demo/**
          - Weight=group,2
        filters:
          - StripPrefix=1
          
      - id: suiyi2
        uri: lb://demo-two
        predicates:
          - Path=/demo/**
          - Weight=group,8
        filters:
          - StripPrefix=1

四、过滤器(拦截)(Filter)

1、简介

过滤器作为网关的其中一个重要功能,就是实现请求的鉴权。

执行顺序:

Spring Cloud Gateway 的 Filter 的执行顺序有两个:“pre” 和 “post”。“pre”和 “post” 分别会在请求被执行前调用和被执行后调用。


Spring Cloud Gateway简单使用_spring_04

Gateway自带过滤器有几十个,常见自带过滤器有:

官网地址:

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories


Spring Cloud Gateway简单使用_java_05

过滤器名称

说明

AddRequestHeader

对匹配上的请求加上Header

AddRequestParameters

对匹配上的请求路由

AddResponseHeader

对从网关返回的响应添加Header

StripPrefix

对匹配上的请求路径去除前缀

PrefixPath

对匹配上的请求路径添加前缀

使用场景:

  • 请求鉴权:如果没有访问权限,直接进行拦截
  • 异常处理:记录异常日志
  • 服务调用时长统计

2、系统内置过滤器使用

**过滤器类型:**Gateway有两种过滤器

  • 局部过滤器:只作用在当前配置的路由上。
  • 全局过滤器:作用在所有路由上。

2.1 添加响应头(AddResponseHeader)

对输出的响应设置其头部属性名称为i-love,值为itheima。

配置文件更新:

# 往响应过滤器中加入信息
   - AddResponseHeader: i-love,itheima

全部配置:

spring:
  cloud:
    gateway:
      # 全局过滤器配置
      default-filters:
     # 往响应过滤器中加入信息
        - AddResponseHeader: i-love,itheima
        
        - AddRequestParameters:
        - AddRequestHeader:
        - StripPrefix:
        - PrefixPath:

结果展示:


Spring Cloud Gateway简单使用_java_06

2.2 增加路由配置(PrefixPath)

在gateway中可以通过配置路由的过滤器PrefifixPath实现映射路径中的前缀添加。可以起到隐藏接口地址的作用,避免接口地址暴露。

# 请求地址添加路径前缀过滤器 
filters:
  - PrefixPath=/user

完整配置:

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route # 路由id,可以随意写 
          # 代理服务地址;lb表示从Eureka中获取具体服务 
          uri: lb://user-service 
          # 路由断言,配置映射路径 
          predicates:
            - Path=/** 
          # 请求地址添加路径前缀过滤器 
          filters:
            - PrefixPath=/user

结果展示:

配置

访问地址

路由地址

PrefifixPath=/user

localhost:10010/findById?id=1

localhost:9091/user/findById?id=1

PrefifixPath=/user/abc

localhost:10010/findById?id=1

localhost:9091/user/abc/findById?id=1

2.3 删除路由配置(StripPrefix)

在gateway中通过配置路由过滤器StripPrefifix,实现映射路径中地址的去除。通过StripPrefifix=1来指定路由要去掉的前缀个数。

如:路径/api/user/1将会被路由到/user/1

filters:
  # 去除路径前缀过滤器
  - StripPrefix=1

完整配置文件

spring:
  cloud:
    gateway:
      routes:
        - id: user-service-route # 路由id,可以随意写
          # 代理服务地址;lb表示从Eureka中获取具体服务
          uri: lb://user-service
          # 路由断言,配置映射路径
          predicates:
            - Path=/**
          # 请求地址添加路径前缀过滤器
          filters:
            # 去除路径前缀过滤器
            - StripPrefix=1

访问效果:

配置

访问地址

路由地址

StripPrefix=1

localhost:10010/api/user/findById?id=1

localhost:9091/user/findById? id=1

StripPrefix=2

localhost:10010/aa/api/user/findById? id=1

localhost:9091/user/findById? id=1

2.4 AddRequestHeader

添加请求头参数,参数和值之间使用逗号分隔

filters:
  - StripPrefix= 1
  - AddRequestHeader=MyHeader,jqk

2.5 AddRequestParameter

添加请求表单参数,多个参数需要有多个过滤器。

filters:
  - AddRequestParameter=name,bjsxt
  - AddRequestParameter=age,123

2.6 DedupeResponseHeader

对指定响应头去重复。

语法:DedupeResponseHeader=响应头参数 响应头参数,strategy

可选参数 strategy 可取值:

  • RETAIN_FIRST:默认值,保留第一个
  • RETAIN_LAST:保留最后一个。
  • RETAIN_UNIQUE:保留唯一的,出现重复的属性值,会保留一个。例如有两个 My:bbb 的属性,最后会只留一个。
filters:
  - StripPrefix= 1
  - DedupeResponseHeader=My Content-Type,RETAIN_UNIQUE

2.7 CircuitBreaker

实现熔断时使用,支持 CircuitBreaker 和 Hystrix 两种

2.8 FallbackHeaders

可以添加降级时的异常信息

2.9 RequestRateLimiter

限流过滤器

2.10 RedirectTo

重定向。

有两个参数,status 和 url。其中 status 应该 300 系列重定向状态码

2.11 RemoveRequestHeader

删除请求头参数

2.12 RemoveResponseHeader

删除响应头参数

2.13 RemoveRequestParameter

删除请求参数

2.14 RewritePath

重写请求路径

2.15 RewriteResponseHeader

重写响应头参数

2.16 SaveSession

如果项目中使用Spring Security和Spring Session整合时,会使用到此属性。

2.17 SecureHeaders

具有权限验证时,建议的头信息内容。

2.18 Retry

设置重试次数

功能和StripPrefix类似。

2.19 RequestSize

请求的最大大小。包含maxSize参数,可以有单位'KB'或'MB'默认为B。

2.20 ModifyRequestBody

修改请求体内容

2.21 ModifyResponseBody

修改响应体内容

2.22 SetPath

当请求路径为/red/blue时,会将/blue发送给下游。

spring:
  cloud:
    routes:
      - id: system
        uri: lb://system
        predicates:
          - Path=/red/{segment}
        filters:
          - SetPath=/{segment}

2.23 SetRequestHeader

替换请求参数头。

2.24 SetResponseHeader

替换相应头参数

2.25 SetStatus

设置相应状态码

3、自定义全局过滤器

放行:

//12. 放⾏
return chain.filter(exchange);

拦截:

//7. 响应中放⼊返回的状态吗, 没有权限访问
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//8. 返回
return response.setComplete()

3.1 假如token为null,则拦截

import org.apache.commons.lang3.StringUtils;
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;

@Configuration
public class MyGlobalFileter implements GlobalFilter, Ordered {


    /**
     * 自定义过滤器规则
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("-----------------全局过滤器MyGlobalFilter---------------------");
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isBlank(token)) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    /**
     * 定义过滤器执行顺序
     * 返回值越小,越靠前执行
     * @return
     */
    @Override
    public int getOrder() {
        return 0;
    }
}

3.2 IP过滤器

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

import java.net.InetSocketAddress;

@Component
public class IPFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("经过IP过滤器");
        ServerHttpRequest request = exchange.getRequest();
        InetSocketAddress remoteAddress = request.getRemoteAddress();
        System.out.println("请求的IP地址为:" + remoteAddress.getHostName());

        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

3.3 请求url过滤器

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

@Component
public class UrlFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("经过url过滤器");
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        System.out.println("请求的url为:" + path);
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

4、自定义可配置过滤器(添加到配置文建)

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.support.GatewayToStringStyler;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;
import java.util.List;

@Component
public class MyRouteGatewayFilterFactory extends AbstractGatewayFilterFactory<MyRouteGatewayFilterFactory.Config> {
    public MyRouteGatewayFilterFactory() {
        super(MyRouteGatewayFilterFactory.Config.class);
    }

    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("在这个位置写点东西传递进来的 name: " + config.getName() + ",age:" + config.getAge());
                return chain.filter(exchange);
            }

            @Override
            public String toString() {
                return GatewayToStringStyler.filterToStringCreator(MyRouteGatewayFilterFactory.this).append("name", config.getName()).toString();
            }
        };
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("name");
    }

    public static class Config {
        private String name;
        private int age;

        public int getAge() {
            return age;
        }

        public void setAge(int age) {
            this.age = age;
        }

        public Config() {
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }
}

添加到配置文件中(application.yaml)

spring:
  application:
    name: sysgateway
  cloud:
    routes:
    #   自定义配置
      - id: myFilter
        uri: lb:/jqk
        predicates:
          - Path=/project/**
        filters:
          - StripPrefix=1
          - name: MyRoute
            args:
           # 传递的参数(name、age)
              name: hello
              age: 12

五、其它配置

1、网关自动映射处理

  • 只要请求地址符合规则:http://gatewayIp:gatewayPort/微服务名称/微服务请求地址
  • 网关自动映射。把请求地址转发到 http://微服务名称/微服务请求地址
  • 如:有微服务,命名为ribbon-app-service
  • 商业开发中:enabled一般不设置,默认为false。避免不必要的自动转发机制。

案例:

请求地址:http://localhost:9999/ribbon-app-service/getArgs?name=admin&age=20
自动转发到:http://ribbon-app-service/getArgs?name=admin&age=20

配置文件

spring:
  application:
    name: sysgateway
  cloud:
    gateway:
      discovery: # 配置网关发现机制
        locator: #  配置处理机制
          enabled: true # 开启网关自动映射处理机制
          lower-case-service-id: true # 开启微服务名称小写转换。Eureka对服务名管理默认全大写。

2、动态路由

#	路由到执行IP
uri: http://127.0.0.1:9091
#	根据服务名称进行路由(从配置中心获取指定IP)
uri: lb://user-service
  • 路由配置中uri所用的协议为lb时,gateway将把user-service解析为实际的主机和端口,并通过Ribbon进行负载均衡。
  • 应该是根据服务名称,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!

测试日志:


Spring Cloud Gateway简单使用_java_07

这次gateway进行路由时,会利用Ribbon进行负载均衡访问。日志中可以看到使用了负载均衡器。


Spring Cloud Gateway简单使用_spring cloud_08

3、跨域配置

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedMethods: # ⽀持的⽅法
              - GET
              - POST
              - PUT
              - DELETE

4、记录执行耗时

//	将开始时间放入请求中
exchange.getAttributes().put("startTime", System.currentTimeMillis());
//	计算执行耗时
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    Long startTime = exchange.getAttribute("startTime");
    Long executeTime = System.currentTimeMillis() - startTime;
}));

完整版:

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Slf4j
@Component
public class UrlFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("经过url过滤器");
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        System.out.println("请求的url为:" + path);
      	exchange.getAttributes().put("startTime", System.currentTimeMillis());

        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            Long startTime = exchange.getAttribute("startTime");
            if (startTime != null) {
                long executeTime = System.currentTimeMillis() - startTime;
                log.info("请求时间:{}", exchange.getRequest().getURI().getRawPath() + "d" + executeTime + "ms");
            }
        }));
    }

    @Override
    public int getOrder() {
        return 2;
    }
}

5、exchange代码信息

//  获取请求头信息
HttpHeaders headers = exchange.getRequest().getHeaders();
String first = exchange.getRequest().getHeaders().getFirst("Content-type");
ServerHttpRequest build = exchange.getRequest().mutate().header("Content-type","json").build();
//  获取请求方式
String name = exchange.getRequest().getMethod().name();
//  获取请求URL地址信息
String host = exchange.getRequest().getURI().getHost();
String path1 = exchange.getRequest().getURI().getPath();
String rawPath = exchange.getRequest().getURI().getRawPath();
//  获取请求属性信息
exchange.getAttributes().put("startTime",123123);
Long startTime1 = exchange.getAttribute("startTime");
//  获取返回体
ServerHttpResponse response = exchange.getResponse();

六、网关限流

1、简介

限流,当我们的系统 被频繁的请求的时候,就有可能 将系统压垮,所以 为了解决这个问题,需要在每⼀个微服务中做限流操作,但是如果有了⽹关,那么就可以在⽹关系统做限流,因为所有的请求都需要先通过⽹关系统才能路由到微服务中。


Spring Cloud Gateway简单使用_java_09

2、令牌桶算法简介

令牌桶算法是⽐较常⻅的限流算法之⼀,⼤概描述如下:

  1. 所有的请求在处理之前都需要拿到⼀个可⽤的令牌才会被处理;
  2. 根据限流⼤⼩,设置按照⼀定的速率往桶⾥添加令牌;
  3. 桶设置最⼤的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
  4. 请求达到后⾸先要获取令牌桶中的令牌,拿着令牌才可以进⾏其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
  5. 令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证⾜够的限流

Spring Cloud Gateway简单使用_spring_10

3、代码实现

3.1 pom.xml依赖

spring cloud gateway 默认使⽤redisRateLimter限流算法来实现。所以我们要使⽤⾸先需要引⼊redis的依赖。

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

3.2 定义KeyResolver

GatewayApplicatioin引导类中添加如下代码,KeyResolver⽤于计算某⼀个类型的限流的KEY也就是说,可以通过KeyResolver来指定限流的Key

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@SpringBootApplication
@EnableDiscoveryClient // 开启Eureka客户端发现服务
public class DemoGatewayApplication {

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

    //    定义一个KeyResolver
    @Bean
    public KeyResolver ipKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono<String> resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
            }
        };
    }
}

3.3 修改配置

修改application.yml中配置项,指定限制流量的配置以及REDIS的配置。

filters:
  - PrefixPath=/test
  - name: RequestRateLimiter
    args:
      key-resolver: "#{@ipKeyResolver}"
      redis-rate-limiter.replenishRate: 1
      redis-rate-limiter.burstCapacity: 1
  • burstCapacity:令牌桶总容量。
  • replenishRate:令牌桶每秒填充平均速率。
  • key-resolver:⽤于限流的键的解析器的 Bean 对象的名字。它使⽤ SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象。

通过在 replenishRate 和中设置相同的值来实现稳定的速率 burstCapacity 。设置 burstCapacity ⾼于时,可以允许临时突发 replenishRate 。在这种情况下,需要在突发之间允许速率限制器⼀段时间(根据 replenishRate ),因为2次连续突发将导致请求被丢弃( HTTP 429 - Too Many Requests key-resolver: "#{@userKeyResolver}" ⽤于通过SPEL表达式来指定使⽤哪⼀个KeyResolver

如上配置:

  • 表示 ⼀秒内,允许 ⼀个请求通过,令牌桶的填充速率也是⼀秒钟添加⼀个令牌。
  • 最⼤突发状况 也只允许 ⼀秒内有⼀次请求,可以根据业务来调整 。

3.4 最终配置:

spring:
  application:
    name: sysgateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
            allowedOrigins: "*" #跨域处理 允许所有的域
            allowedMethods: # ⽀持的⽅法
              - GET
              - POST
              - PUT
              - DELETE
    routes:
      - id: goods
        uri: lb://goods
        predicates:
          - Path=/goods/**
        filters:
          - StripPrefix= 1
          - name: RequestRateLimiter #请求数限流 名字不能随便写
            args:
              key-resolver: "#{@ipKeyResolver}"
              redis-rate-limiter.replenishRate: 1
              redis-rate-limiter.burstCapacity: 1
      - id: system
        uri: lb://system
        predicates:
          - Path=/system/**
        filters:
          - StripPrefix= 1
    # 配置Redis 127.0.0.1可以省略配置
    redis:
      host: 192.168.200.128
      port: 6379
server:
  port: 9101
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:6868/eureka
  instance:
    prefer-ip-address: true


标签:exchange,Spring,springframework,路由,Cloud,import,org,Gateway,cloud
From: https://blog.51cto.com/u_14883832/6469736

相关文章

  • mmhmm重塑视频会议、2020新款emoji可爱来袭、微软将推云游戏服务xCloud等| Decode the
    Social MediaSucks.DecodetheWeek≠音视频技术周刊 NewsBriefing1. Evernote前CEO推出虚拟摄影棚应用mmhmm重塑视频会议PhilLibin带领Evernote创造辉煌后,再次回到消费与企业应用的交界,推出虚拟相机云服务mmhmm(中文发音是“嗯哼”)。mmhmm可在Zoom、GoogleMeet、YouTube以......
  • Spring 配置 事务的几种方式
    评:Spring配置文件中关于事务配置总是由三个组成部分,DataSource、TransactionManager和代理机制这三部分,无论是那种配置方法,一般变化的只是代理机制这块! 首先我创建了两个类,一个接口一个实现:1.package2.publicinterface3.publicvoid4.} 实现:1.package2.import3.im......
  • cloudflare 通过api删除ns 记录
    取dns记录idcurl--requestGET\--urlhttps://api.cloudflare.com/client/v4/zones/zone_id/dns_records\--header'Content-Type:application/json'\--header'X-Auth-Email:email'\--header'X-Auth-KEY:global_key' 通过dnsid删除......
  • IBM Cloud:裸金属服务器+多云策略助力音视频解决方案成功出海
    到底什么是公有云、私有云和混合云?疫情给云服务厂商带来了哪些挑战?IBM是如何助力音视频解决方案成功出海的?“后疫情”时代音视频的下一个风口在哪里?对此,LiveVideoStack很荣幸地采访到了来自IBM云平台事业部,资深云计算架构师——胡磊,聊一聊他对这些问题的看法和观点。胡磊技术访谈#0......
  • springboot 测试用例 gradle
    在springboot2.4.5之后的变成了jinut5直接引用即可不需要排除org.junit.jupiter.api.Testorg.springframework.boot:spring-boot-starter-test测试数据H2packagecom.example.test_pro_gradle;importorg.junit.jupiter.api.Test;importorg.slf4j.Logger;impor......
  • springcloud 启动失败 YAMLException java.nio.charset.MalformedInputException Inp
     上面这个是错误信息,但是该微服务在本地启动的时候是可以的,但是本地打成jar包本地执行的时候就失败。需要再Java-jar的中间加一下字符编码java-Dfile.encoding=utf-8-jar  myself.jar   myself.jar是自己的jar包问题解决......
  • s1sh整合实例 Strut1.2+Spring2.6+Hibernate3.2
    [code]开发环境:MyEclipse8.5+Mysql说明:本实例是简单注册程序(只有两个属性)数据库脚本:user.sqlCREATETABLE`user`(`Id`int(11)NOTNULLAUTO_INCREMENT,`username`varchar(255)DEFAULTNULL,`password`varchar(255)DEFAULTNULL,P......
  • Spring下的权限框架 spring security总结
    Spring下的权限框架springsecurity总结[code]springsecurity总结首先导入springsecurity所需要的jar包spring-security-core-2.0.5.RELEASE.jarspring-security-core-tiger-2.0.5.RELEASE.jar一.配置过滤器在web.xml中定义如下过滤器<filter><fil......
  • SpringCloudAlibaba
    一、SpringCloudAlibaba功能组件?Sentinel:流量控制,熔断降级,系统负载保护等方面。Nacos:注册中心,配置管理中心。RocketMq:分布式消息系统。Dubbo:java的RPC框架。Seata:分布式事务解决方案。AlibabaCloudOSS:阿里云对象存储服务。AlibabaCloudSchedulerX:分布式任务调度产品......
  • 跨越式初学SpringBoot的各种问题《一》
    前提:本人没有学过一点SSM,在学SpringBoot之前,上网搜索了各种回答,关于能否跨越直接学SpringBoot,得到的都是肯定回答可以;在本人觉得promising,开始在哔哩哔哩大学,翻找各种SpringBoot叫教学视频,每一个教程打开第一集就是,要求懂SSM(谁懂啊bleak)。然而,我依然坚定开始了零SSM基础的学习!应......