• spring-cloud-gateway


    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使用阻塞 API,它不支持任何长连接,如 WebSockets,Spring Cloud Gateway 使用非阻塞 API,支持 WebSockets,支持限流等新特性。

    Spring Cloud Gateway

    Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

    Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

    相关概念:

    • Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
    • Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
    • Filter(过滤器):这是org.springframework.cloud.gateway.filter.GatewayFilter的实例,我们可以使用它修改请求和响应。

    工作流程:

    客户端向 Spring Cloud Gateway 发出请求。如果 Gateway Handler Mapping 中找到与请求相匹配的路由,将其发送到 Gateway Web Handler。Handler 再通过指定的过滤器链来将请求发送到我们实际的服务执行业务逻辑,然后返回。 过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前(“pre”)或之后(“post”)执行业务逻辑。

    Spring Cloud Gateway 的特征:

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

    一、新建spring-cloud-gateway服务工程

     1.选中spring-cloud-gate包的支持,pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>lf.liyouyou</groupId>
        <artifactId>spring-cloud-gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-cloud-gateway</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </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>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

      2.配置yml中路由规则

      

    spring:
      application:
        name: gateway-service
      cloud:
        gateway:
          routes:
         
          - id: route_configclient  # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello
            uri: http://localhost:9004
            predicates:
            - Path=/gateway/*
            filters:
            - StripPrefix=1  #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway
    server:
      port: 9005

    3.启动项目并测试,发现可以跳转并返回值

     二、配置Cookie路由

    修改yml配置,新增Cookie路由规则

    spring:
      application:
        name: gateway-service
      cloud:
        gateway:
          routes:
         
          - id: route_configclient  # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello
            uri: http://localhost:9004
            predicates:
            - Path=/gateway/*
            filters:
            - StripPrefix=1  #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway
    
          - id: cookie_route  # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello
            predicates:
            - Cookie=lf,lf.liyouyou
            uri: https://home.cnblogs.com/u/flgb/
    server:
      port: 9005

     启动,用postman 进行测试,直接访问http://localhost:9005/  返回404

    添加cookie,配置key=value

     再次发起请求,注意默认是get请求,返回了页面信息,断言匹配成功

    查看请求中的cookie ,对比yml配置

     三、自定义Header路由规则

      1. 可以参照CookieRoutePredicateFactory自定义路由一个AuthRoutePredicateFactory用来判断header头的路由,其中RoutePredicateFactory是固定后缀

      AuthRoutePredicateFactory类代码如下:

    package lf.liyouyou.Config;
    
    import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
    import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory;
    import org.springframework.http.HttpHeaders;
    import org.springframework.stereotype.Component;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.server.ServerWebExchange;
    
    import javax.validation.constraints.NotEmpty;
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    @Component
    public class AuthRoutePredicateFactory extends AbstractRoutePredicateFactory<AuthRoutePredicateFactory.Config> {
    
        public static final String NAME_KEY = "name";
    
        public AuthRoutePredicateFactory() {
            super(Config.class);
        }
    
        @Override
        public Predicate<ServerWebExchange> apply(Config config) {
            //自定义断言规则,判断header中是否包含某个值
            return (exchange->{
                HttpHeaders headers = exchange.getRequest().getHeaders();
                List<String> list = headers.get(config.getName());
                return list.size()>0;
            });
        }
    
        @Override
        public List<String> shortcutFieldOrder() {
            //自定义属性顺序,配置的断言时进行顺序匹配,
            // 这里就定义一个属性值,则第一个值就是config.name的值
            return Arrays.asList(NAME_KEY);
        }
    
        @Validated
        public static class Config {
            @NotEmpty
            private String name;
    
            public void setName(String name) {
                this.name = name;
            }
    
            public Config() {
            }
    
            public String getName() {
                return this.name;
            }
    
    
        }
    }

     2. 配置application.yml路由策略

    spring:
      application:
        name: gateway-service
      cloud:
        gateway:
          routes:
          - id: route_configclient  # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello
            uri: http://localhost:9004
            predicates:
            - Path=/gateway/*
            filters:
            - StripPrefix=1  #前缀, 在当前路径匹配中表示去掉第一个前缀 /gateway
    
          - id: cookie_route  # 请求 http://localhost:9005/gateway/hello转发到 http://localhost:9004/hello
            predicates:
            - Cookie=lf,lf.liyouyou
            uri: https://home.cnblogs.com/u/flgb/
    
          - id: header_route
            predicates:
            - Path=/header/**
            - Auth=Authorization
            uri: https://home.cnblogs.com/u/flgb/
            filters:
            - StripPrefix=1  #前缀, 在当前路径匹配中表示去掉第一个前缀 /header
    server:
      port: 9005

     3. 启动工程,可以看到控制台输出:

           证明路由配置生效

     4. postman测试

       直接访问

      

      配置上header参数值,再访问

     四、自定义RouteFilter

      Configuration类

      

    package lf.liyouyou.Config;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
    import org.springframework.stereotype.Component;
    import reactor.core.publisher.Mono;
    
    import javax.validation.constraints.NotEmpty;
    import java.util.Arrays;
    import java.util.List;
    
    //order过滤器优先级
    @Component
    public class LFGatewayFilterFactory extends AbstractGatewayFilterFactory<LFGatewayFilterFactory.LFConfig> {
    
        public static final String NAME_KEY = "name";
    
        Logger logger = LoggerFactory.getLogger(LFGatewayFilterFactory.class);
    
        public LFGatewayFilterFactory() {
            super(LFConfig.class);
        }
    
        @Override
        public List<String> shortcutFieldOrder() {
            return Arrays.asList(NAME_KEY);
        }
    
        @Override
        public GatewayFilter apply(LFConfig config) {
            //Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
            //Fiter pre/post
            return ((exchange,chain)->{
                //TODO
                logger.info("pre fiter request,name: {}",config.getName());
                return chain.filter(exchange).then(
                        Mono.fromRunnable(()->{
                            //TODO
                            logger.info("post :response filter!");
                        })
                );
            });
        }
    
        public static class LFConfig {
            @NotEmpty
            private String name;
    
            public void setName(String name) {
                this.name = name;
            }
    
            public LFConfig() {
            }
    
            public String getName() {
                return this.name;
            }
    
    
        }
    }

    yml配置filter,新增标黄地方

    spring:
      application:
        name: gateway-service
      cloud:
        gateway:
          routes:
          - id: route_configclient1  #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello
            uri: http://localhost:9003  #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1
            predicates:
            - Path=/gateway/**  #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84
            filters:
            - StripPrefix=1
            - LF= hello lf

    重新启动,访问http://localhost:9005/gateway/hello,查看控制台日志,发现已经生效

    五、GlobalFIlter实现负载均衡

    1、spring-cloud-gateway添加注册中心的依赖

      pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>lf.liyouyou</groupId>
        <artifactId>spring-cloud-gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-cloud-gateway</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </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>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    2.yml新增标黄配置,开启注册中心支持,配置负载均衡路由

    spring:
      application:
        name: gateway-service
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true
              lower-case-service-id: true
          routes:
          - id: route_configclient1  #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello
            uri: http://localhost:9003  #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1
            predicates:
            - Path=/gateway/**  #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84
            filters:
            - StripPrefix=1
            - LF= hello lf
          - id: route_configclient  # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello
            uri: http://localhost:9004
            predicates:
            - Path=/gateway/*
            filters:
            - StripPrefix=1  #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /gateway
    
          - id: cookie_route  # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello
            predicates:
            - Cookie=lf,lf.liyouyou
            uri: https://home.cnblogs.com/u/flgb/
    
          - id: header_route
            predicates:
            - Path=/header/**
            - Auth=Authorization
            uri: https://home.cnblogs.com/u/flgb/
            filters:
            - StripPrefix=1  #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /header
    
          - id: lb_route
            predicates:
            - Path=/lb/**
            filters:
            - StripPrefix=1
            uri: lb://spring-cloud-config-client
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8000/eureka/
    server:
      port: 9005

    3、取消spring-cloud-config-client服务只能启动单个实例的限制

      4、修改/hellolf返回值

    package lf.liyouyou.controller;
    
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class HelloController {
    
        @RequestMapping("/hellolf")
        public String Hellolf(){
            return "hello lf 9999";
        }
    }

     

     5、修改端口为9999,再次启动,看到注册中心上有两个spring-cloud-config-client服务

     6、测试结果如下

     

    六、基于redis限流器的实现

    1、新增依赖pom.xml

      

    <?xml version="1.0" encoding="UTF-8"?>
    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>lf.liyouyou</groupId>
        <artifactId>spring-cloud-gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-cloud-gateway</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
                <version>2.0.5.RELEASE</version>
            </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>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    2.新增keyResolver代码

    package lf.liyouyou.Config;
    
    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().getAddress().getHostAddress());
        }
    }

    3、新增yml配置

    spring:
      application:
        name: gateway-service
      redis:
        host: 192.168.31.151
        port: 6379
        password:
    
      cloud:
        gateway:
          discovery:
            locator:
              enabled: true
              lower-case-service-id: true
          routes:
          - id: route_configclient1  #u8BF7u6C42 http://localhost:9005/gateway/hellolfu4F1Au8F6Cu53D1u5230http://localhost:9003/hello
            uri: http://localhost:9003  #u5728u670Du52A1u6CE8u518Cu4E2Du5FC3u627Eu670Du52A1u540Du4E3A data-produceru7684u670Du52A1
            predicates:
            - Path=/gateway/**  #u8BBEu7F6Eu8DEFu7531u65ADu8A00,u4EE3u7406servicerIdu4E3Adata-service1u7684/ data-service1 /u8DEFu5F84
            filters:
            - StripPrefix=1
            - LF= hello lf
          - id: route_configclient  # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello
            uri: http://localhost:9004
            predicates:
            - Path=/gateway/*
            filters:
            - StripPrefix=1  #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /gateway
    
          - id: cookie_route  # u8BF7u6C42 http://localhost:9005/gateway/hellou8F6Cu53D1u5230 http://localhost:9004/hello
            predicates:
            - Cookie=lf,lf.liyouyou
            uri: https://home.cnblogs.com/u/flgb/
    
          - id: header_route
            predicates:
            - Path=/header/**
            - Auth=Authorization
            uri: https://home.cnblogs.com/u/flgb/
            filters:
            - StripPrefix=1  #u524Du7F00uFF0C u5728u5F53u524Du8DEFu5F84u5339u914Du4E2Du8868u793Au53BBu6389u7B2Cu4E00u4E2Au524Du7F00 /header
    
          - id: lb_route
            predicates:
            - Path=/lb/**
            filters:
            - StripPrefix=1
            uri: lb://spring-cloud-config-client
    
          - id: ratelimiter_route
            predicates:
            - Path=/ratelimiter/**
            filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                deny-empty-key: true
                key-resolver: "#{@ipAddressKeyResolver}" #默认类名称首字母小写
                redis-rate-limite  r.replenishRate: 1
                redis-rate-limiter.burstCapacity: 2
            uri: lb://spring-cloud-config-client
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8000/eureka/
    server:
      port: 9005

    4.重新启动spring-cloud-gateway测试,重复刷新 http://localhost:9005/ratelimiter/hellolf,出现:429代表被限流

    六、GateWay动态路由的实现

      gateway官网

         https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#creating-and-deleting-a-particular-route 官网预留了actuator接口,

      可以动态创建、删除路由、路由刷新机制,不过默认是存放在内存中的,重启服务后新创建的、删除的都会消失。将其改造存储在redis中支持gateway的动态路由

      可以参考docker篇安装redis镜像。https://i.cnblogs.com/posts?cateId=1625602

      1.spring-cloud-gateway导入包,pom.xml

      

    <?xml version="1.0" encoding="UTF-8"?>
    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.3.4.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
        <groupId>lf.liyouyou</groupId>
        <artifactId>spring-cloud-gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>spring-cloud-gateway</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
            <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
                <version>2.0.5.RELEASE</version>
            </dependency>-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.72</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </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>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

    编写自定义存储类:

    package lf.liyouyou.Config;
    
    import com.alibaba.fastjson.JSON;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cloud.gateway.route.RouteDefinition;
    import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    import reactor.core.publisher.Flux;
    import reactor.core.publisher.Mono;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    
    @Component
    public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
    
        public static final String GATEWAY_ROUTE_KEY = "gateway_route_key";
    
        @Autowired
        RedisTemplate redisTemplate;
    
        @Override
        public Flux<RouteDefinition> getRouteDefinitions() {
            ArrayList<RouteDefinition> routeDefinitions = new ArrayList<>();
            redisTemplate.opsForHash().values(GATEWAY_ROUTE_KEY).stream()
                    .forEach(route->{
                routeDefinitions.add(JSON.parseObject(route.toString(),RouteDefinition.class));
            });
            return Flux.fromIterable(routeDefinitions);
        }
    
        @Override
        public Mono<Void> save(Mono<RouteDefinition> route) {
            return route.flatMap(routeDefinition -> {
                redisTemplate.opsForHash().put(GATEWAY_ROUTE_KEY,routeDefinition.getId(), JSON.toJSONString(routeDefinition));
                return Mono.empty();
            });
        }
    
        @Override
        public Mono<Void> delete(Mono<String> routeId) {
            return routeId.flatMap(id->{
                if(redisTemplate.opsForHash().hasKey(GATEWAY_ROUTE_KEY,id)){
                    redisTemplate.opsForHash().delete(GATEWAY_ROUTE_KEY,id);
                    return Mono.empty();
                }
                return Mono.defer(()->Mono.error(new RuntimeException("not found the RouteDefinition Exception!")));
            });
        }
    }

    yml添加redis和actuator配置

    spring:
      application:
        name: gateway-service
      redis:
        host: 192.168.31.151
        port: 6379
        password:
    management:
      endpoints:
        web:
          exposure:
            include: "*"

    启动:post测试,官网资料添加路由截图如下:

     postman测试返回,1成功

    报文如下:

    "filters": [{
          "args":{
              "_genkey_0":1
          },
          "name": "StripPrefix"
      }],
      "uri": "https://www.baidu.com",
      "order": 0
    }

     访问http://localhost:9005/actuator/gateway/routes 查看最新路由信息(基于事件机制刷新),也可以调用(http://localhost:9005/actuator/gateway/routes/refresh)进行刷新,查询baidu_route发现已存在,访问http://localhost:9005/baidu 发现已经可以跳转到百度

    查看redis保存路由的信息:

    docker exec -it 启动的redis容器名称 redis-cli 进入redis client端

     可以看到redis中已经保存了gateway_route_key的相关信息。

    我们重新启动spring-cloud-gateway,再次访问http://localhost:9005/baidu 发现还是跳转到了百度。证明动态路由永久生效。

  • 相关阅读:
    触动心灵的话语
    join和os.path.join 的用法
    os.path.join 的用法
    Python中函数的定义必须在调用的前面
    矩阵和数组的区别
    Object detection with deep learning and OpenCV
    YOLO Object Detection with OpenCV
    Python-OpenCV中VideoCapture类的使用
    Object Detection: Face Detection using Haar Cascades
    有关目标检测的文章
  • 原文地址:https://www.cnblogs.com/flgb/p/13888404.html
Copyright © 2020-2023  润新知