• (转)SpringCloud之服务网关Gateway


    原文网址 https://blog.csdn.net/qq_41402200/article/details/94333830

    前言

      SpringCloud 是微服务中的翘楚,最佳的落地方案。

      Spring Cloud Gateway 是 Spring Cloud 新推出的网关框架,之前是 Netflix Zuul。网关通常在项目中为了简化

      前端的调用逻辑,同时也简化内部服务之间互相调用的复杂度;具体作用就是转发服务,接收并转发所有内外

      部的客户端调用;其他常见的功能还有权限认证,限流控制等等。

      本博客会提到网关的基本转发功能,熔断功能,限流功能以及功能的综合使用。

    源码

      GitHub地址:https://github.com/intomylife/SpringCloud

    环境

    • JDK 1.8.0 +
    • Maven 3.0 +
    • SpringBoot 2.0.3
    • SpringCloud Finchley.RELEASE
    • Redis 3.0 +

    开发工具

    • IntelliJ IDEA

    正文

    commons 工程

    commons 工程 - POM 文件

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-commons</artifactId>
        <version>1.0</version>
     
        <!-- 工程名称和描述 -->
        <name>springcloud-gateway-commons</name>
        <description>公用工程</description>
     
        <!-- 打包方式 -->
        <packaging>jar</packaging>
     
        <!-- 在 properties 下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- 编码 -->
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <!-- jdk -->
            <java.version>1.8</java.version>
     
            <!-- SpringBoot -->
            <platform-bom.version>Cairo-SR3</platform-bom.version>
     
            <!-- SpringCloud -->
            <spring-cloud-dependencies.version>Finchley.RELEASE</spring-cloud-dependencies.version>
        </properties>
     
        <!-- 加入依赖 -->
        <dependencies>
     
        </dependencies>
     
        <!-- 依赖 jar 包版本管理的管理器 -->
        <!-- 如果 dependencies 里的 dependency 自己没有声明 version 元素,那么 maven 就此处来找版本声明。 -->
        <!-- 如果有,就会继承它;如果没有就会报错,告诉你没有版本信息 -->
        <!-- 优先级:如果 dependencies 里的 dependency 已经声明了版本信息,就不会生效此处的版本信息了 -->
        <dependencyManagement>
            <dependencies>
                <!-- SpringBoot -->
                <dependency>
                    <groupId>io.spring.platform</groupId>
                    <artifactId>platform-bom</artifactId>
                    <version>${platform-bom.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <!-- SpringCloud -->
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>${spring-cloud-dependencies.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>
    • 配置一些共用依赖

    commons 工程 - 项目结构

    service 工程

      ① 此工程下有四个模块:一个注册中心,一个网关以及两个提供者

      ② 两个提供者除端口不一致以外,其他代码基本一致

     

    registry-service(注册中心)

    registry-service - POM 文件

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
     
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-registry-service</artifactId>
        <version>1.0</version>
     
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-registry-service</name>
        <description>注册中心</description>
     
        <!-- 打包方式 -->
        <packaging>jar</packaging>
     
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
     
        </properties>
     
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 服务注册中心 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
     
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
     
    </project>
    • 主要加入 spring-cloud-starter-netflix-eureka-server 依赖

    registry-service - application.yml 配置文件

    # 端口
    server:
      port: 8761
     
    # 应用名称
    spring:
      application:
        name: eureka-server
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        # 是否向注册中心注册自己
        registerWithEureka: false
        # 是否向注册中心获取注册信息
        fetchRegistry: false
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
    • 这里使用了默认的 8761 端口,当然也可以更改,不过在发现调用服务端的注册中心地址端口要与它一致

    registry-service - 启动类

    package com.zwc;
     
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
     
    @SpringBootApplication
    @EnableEurekaServer
    public class SpringcloudGatewayRegistryServiceApplication {
     
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayRegistryServiceApplication.class, args);
        }
     
    }

    在启动类中添加 @EnableEurekaServer 注解表示此工程是注册中心

    registry-service - 启动项目

      1. 项目启动成功后访问 http://localhost:8761/ 即可看到 eureka-server 主页面

      注:由于服务工程 A 和服务工程 B 除端口不一致以外,其他代码基本一致,所以服务工程 B 不再赘述

    a-service(服务工程 A)

    a-service - POM 文件

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-a-service</artifactId>
            <version>1.0</version>
        </parent>
     
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-a-service-core</artifactId>
        <version>1.0</version>
     
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-a-service-core</name>
        <description>服务工程 - A 核心</description>
     
        <!-- 打包方式 -->
        <packaging>jar</packaging>
     
        <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->
        <properties>
     
        </properties>
     
        <!-- 加入依赖 -->
        <dependencies>
            <!-- commons工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-commons</artifactId>
                <version>1.0</version>
            </dependency>
     
            <!-- api工程 依赖 -->
            <dependency>
                <groupId>com.zwc</groupId>
                <artifactId>springcloud-gateway-a-service-api</artifactId>
                <version>1.0</version>
            </dependency>
     
            <!-- springboot web 依赖 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
     
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
     
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
     
    </project>
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖

    a-service - application.yml 配置文件

    # 端口
    server:
      port: 9000
     
    # 应用名称
    spring:
      application:
        name: gateway-service
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
    • 注意此处配置注册中心地址的端口为 8761 也就是上面注册中心工程配置的端口

    a-service - controller 前端控制器(提供服务)

    package com.zwc.a.controller;
     
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    /*
     * @ClassName ASayHelloController
     * @Desc TODO   Say Hello
     * @Date 2019/5/20 23:24
     * @Version 1.0
     */
    @RestController
    public class ASayHelloController {
     
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   读取配置文件中的端口
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @Value("${server.port}")
        private String port;
     
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   Say Hello
         * @Date 2019/5/20 23:24
         * @Version 1.0
         */
        @RequestMapping("/hello")
        public String hello(){
            return "Hello!I'm a. port:" + port;
        }
     
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:28
         * @Version 1.0
         */
        @RequestMapping("/name")
        public String name(String name){
            return "My name is " + name + ". aaa";
        }
     
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/23 16:52
         * @Version 1.0
         */
        @RequestMapping("/age")
        public String age(String age){
            return "I am " + age + " years old this year. aaa";
        }
     
        /*
         * @ClassName ASayHelloController
         * @Desc TODO   接收从网关传入的参数
         * @Date 2019/6/29 22:00
         * @Version 1.0
         */
        @RequestMapping("/routeAll")
        public String routeAll(String pass) {
            return "Can I pass? " + pass + "! port:" + port;
        }
     
    }
    • 提供输出字符串服务,供网关调用

    a-service - 启动类

    package com.zwc;
     
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
     
    @SpringBootApplication
    @EnableEurekaClient
    public class SpringcloudGatewayAServiceCoreApplication {
     
        public static void main(String[] args) {
            SpringApplication.run(SpringcloudGatewayAServiceCoreApplication.class, args);
        }
     
    }
    

    添加 @EnableEurekaClient 注解表示此工程可以向注册中心提供服务

    a-service - 启动项目

      1. 刷新 http://localhost:8761/(注册中心)可以看到服务已经被注册进来了

      2. 项目启动成功后访问:http://localhost:9000/hello

      3. 输出内容:'Hello!I'm a. port:9000'

      4. 同样启动服务工程 B后,刷新 http://localhost:8761/(注册中心)

      5. 项目启动成功后访问:http://localhost:9001/hello

      6. 输出内容:'Hello!I'm b. port:9001'

      7. 其他接口是下面网关服务启动后转发调用的,也是本博客的重头戏

    master-service(网关)

    master-service - POM 文件

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
     
        <!-- 继承父 -->
        <parent>
            <groupId>com.zwc</groupId>
            <artifactId>springcloud-gateway-service</artifactId>
            <version>1.0</version>
        </parent>
     
        <!-- 三坐标 -->
        <groupId>com.zwc</groupId>
        <artifactId>springcloud-gateway-master-service</artifactId>
        <version>1.0</version>
     
        <!-- 工程名称描述 -->
        <name>springcloud-gateway-master-service</name>
        <description>Spring Cloud Gateway 服务网关</description>
     
        <!-- 打包方式 -->
        <packaging>jar</packaging>
     
        <!-- 在 properties下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->
        <properties>
            <!-- ali json -->
            <fastjson.version>1.2.47</fastjson.version>
        </properties>
     
        <!-- 加入依赖 -->
        <dependencies>
            <!-- 提供者消费者 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
     
            <!-- gateway -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
     
            <!-- redis -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            </dependency>
     
            <!-- hystrix -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
     
            <!-- ali json依赖 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
        </dependencies>
     
        <!-- 插件依赖 -->
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
     
    </project>
    • 加入 spring-cloud-starter-netflix-eureka-client 依赖:提供和注册服务
    • 加入 spring-cloud-starter-gateway 依赖:gateway
    • 加入 spring-boot-starter-data-redis-reactive 依赖:结合 Redis 限流
    • 加入 spring-cloud-starter-netflix-hystrix 依赖:熔断器

    master-service - application.yml 配置文件

    # 端口
    server:
      port: 8000
     
    spring:
      profiles:
        # 指定配置
        # route_simple:简单尝试
        # route_stripPrefix:截取请求
        # route_uri:转发指定地址并传入参数
        # route_addRequestParameter:转发指定服务并传入参数
        # route_hystrix:熔断
        # route_requestRateLimiter:限流
        # route_all:综合
        active: route_simple
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
     
    ---
     
    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    • 注意配置注册中心地址的端口都为 8761 也就是上面注册中心工程配置的端口
    • 每一对 '---' 符号中的配置文件都是单独的,使用 spring.profiles.active 指定
    • 每一对 '---' 符号中的配置文件都只配置了一个 route(路由)
    • route(路由)由四部分组成,其中 filters 不是必须参数
    • 唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)

    master-service - 简单尝试

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 简单尝试
      profiles: route_simple
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   简单尝试
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive
            - Path=/archive

      1. 停止注册中心工程(registry-service)、服务工程 A 和服务工程 B

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_simple

      3. 上面配置文件内容意思是当访问 http://localhost:8000/archive (网关地址/archive)

          会被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明服务转发成功

    master-service - 截取请求

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 截取请求
      profiles: route_stripPrefix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   截取请求
          - id: route_simple
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: https://www.zouwencong.com
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉
            - Path=/str/archive
            filters:
            ## 截取路径位数
            - StripPrefix=1
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_stripPrefix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/str/archive (网关地址/str/archive)截取 /str 部分,

          截取后被转发到 https://www.zouwencong.com/archive/ (uri/archive)

      4. 启动注册中心工程(registry-service)和网关工程(master-service)

      5. 项目启动成功后访问:http://localhost:8000/str/archive

      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/

      7. 证明路径被截取并服务转发成功

    master-service - 转发指定地址并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定地址并传入参数
      profiles: route_uri
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: route_uri
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:9000
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=name, zwc
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

    1. 停止注册中心工程(registry-service)和网关工程(master-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_uri

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/name (网关地址/name)

          会被转发到 http://localhost:9000/name(uri/name),并传入 'name=zwc' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      5. 项目启动成功后访问:http://localhost:8000/name

      6. 输出内容:'My name is zwc. aaa'(通过网关转发的参数有值)

      7. 打开新页面访问:http://localhost:9000/name

      8. 输出内容:'My name is null. aaa'(问的直接访参数没有值)

      9. 证明转发指定地址并传入参数成功

    master-service - 转发指定服务并传入参数

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 转发指定服务并传入参数
      profiles: route_addRequestParameter
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数
          - id: route_addRequestParameter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug
    

     1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_addRequestParameter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      6. 项目启动成功后访问:http://localhost:8000/age

      7. 这时可能会报错 500.错误信息为 'Unable to find instance for gateway-service'

      8. 这种情况不要慌张,只是服务还没有被注册到注册中心,稍等片刻再访问

      9. 多次访问:http://localhost:8000/age

     10. 轮流输出内容:'I am three years old this year. aaa' 和 'I am three years old this year. bbb'

     11. 此时还通过网关达到了负载均衡的效果

     12. 证明转发指定服务并传入参数成功

    master-service - 熔断

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 熔断
      profiles: route_hystrix
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   熔断
          - id: route_hystrix
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

     1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_hystrix

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足

          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册

          服务名。

      5. 此处还多配置了一个过滤器 '- name: Hystrix'(熔断)

      6. 当请求服务出错时,会调用 fallback,路径为:http://localhost:8000/fallback (网关地址/fallback)

      7. 此时就需要如下前端控制器

    master-service - 熔断 - controller

    package com.zwc.gateway.hystrix;
     
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    /**
     * @ClassName FallbackController
     * @Desc TODO   网关断路器
     * @Date 2019/6/23 19:33
     * @Version 1.0
     */
    @RestController
    public class FallbackController {
     
        /*
         * @ClassName FallbackController
         * @Desc TODO   网关断路器
         * @Date 2019/6/23 19:35
         * @Version 1.0
         */
        @RequestMapping("/fallback")
        public String fallback() {
            return "I'm Spring Cloud Gateway fallback.";
        }
     
    }
    

      7. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      8. 项目启动成功后访问:http://localhost:8000/age

      9. 输出内容:'I'm Spring Cloud Gateway fallback.'

     10. 证明熔断成功

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 限流
      profiles: route_requestRateLimiter
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   限流
          - id: route_requestRateLimiter
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 添加指定参数
            - AddRequestParameter=age, three
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

     1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值

          更改为 route_requestRateLimiter

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)

          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)

      4. 注意此处还需要配置 redis 的连接信息

      5. 注意此处是结合 redis 实现的限流,所以 filter 过滤器的 name 必须为 RequestRateLimiter

      6. 并且通过实现 KeyResolver 类来自定义限流策略,如下

    master-service - 限流 - 策略

    package com.zwc.gateway.config.filters;
     
    import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
     
    /**
     * @ClassName UriKeyResolver
     * @Desc TODO   Spring Cloud Gateway 网关限流过滤器
     * @Date 2019/6/23 17:59
     * @Version 1.0
     */
    public class UriKeyResolver implements KeyResolver {
     
        /*
         * @ClassName UriKeyResolver
         * @Desc TODO   根据请求的 uri 限流
         * @Date 2019/6/29 17:25
         * @Version 1.0
         */
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            return Mono.just(exchange.getRequest().getURI().getPath());
        }
     
    }

      7. 启动本地 redis(redis-server.exe) 服务

      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      9. 项目启动成功后访问:http://localhost:8000/age

      9. 此时限流却无论如何都不生效,原因有如下两点

    ① redis-server 版本过低!我 Windows 本地是 redis-2.4.2 版本的,要用 3 以上的版本!!!

    ② 数据在 redis 中存储的时间只有几秒,所以得使用 monitor 指令来动态的观察!!!

     10. 打开 redis-cli.exe,输入命令 monitor 

     11. 快速刷新地址:http://localhost:8000/age

     12. 页面上会出现 429,redis-cli.exe 中会出现很多数据交互(request_rate_limiter.xxx 开头的 key)

     13. 证明限流成功

    master-service - 综合

    spring:
      # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。
      ## 综合
      profiles: route_all
      redis:
        host: localhost
        port: 6379
        database: 0
      application:
        # 应用名称
        name: gateway-master
      cloud:
        gateway:
          discovery:
            locator:
              # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
              enabled: true
          # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
          routes:
          # 路由标识(id:标识,具有唯一性)   综合
          - id: route_all
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: lb://gateway-service
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
            ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉
            - Path=/all/routeAll
            ## 匹配 GET 请求
            - Method=GET
            # 过滤器(filters:过滤器,过滤规则)
            filters:
            ## 截取路径位数
            - StripPrefix=1
            ## 添加指定参数
            - AddRequestParameter=pass, yes
            ## 熔断
            - name: Hystrix
              args:
                name: fallbackcmd
                ### fallback 时调用的方法 http://localhost:8000/fallback
                fallbackUri: forward:/fallback
            ## 限流
            - name: RequestRateLimiter
              args:
                ### 限流过滤器的 Bean 名称
                key-resolver: '#{@uriKeyResolver}'
                ### 希望允许用户每秒处理多少个请求
                redis-rate-limiter.replenishRate: 1
                ### 用户允许在一秒钟内完成的最大请求数
                redis-rate-limiter.burstCapacity: 3
     
    eureka:
      instance:
        # 使用 ip 代替实例名
        prefer-ip-address: true
        # 实例的主机名
        hostname: ${spring.cloud.client.ip-address}
        # 实例的 ID 规则
        instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
      client:
        serviceUrl:
          # 注册中心地址
          defaultZone: http://${eureka.instance.hostname}:8761/eureka/
     
    logging:
      level:
        # log 级别
        org.springframework.cloud.gateway: debug

      1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_all

      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/all/routeAll (网关地址/all/routeAll)截取 /all 部分,

          会被转发到 http://gateway-service/routeAll(uri/routeAll),并传入 'pass=yes' 参数(注意为 Get 请求)

      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)

      5. 项目启动成功后访问:http://localhost:8000/all/routeAll

      6. 首先会返回 'I'm Spring Cloud Gateway fallback.',因为服务还未被注册到注册中心

      7. 然后会返回 '{"msg":"缺少凭证","code":-1}',因为配置了全局过滤器,如下

    package com.zwc.gateway.config.filters;
     
    import com.alibaba.fastjson.JSONObject;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.Ordered;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.http.server.reactive.ServerHttpResponse;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    import org.springframework.core.io.buffer.DataBuffer;
     
    import java.net.InetSocketAddress;
    import java.nio.charset.StandardCharsets;
     
    /**
     * @ClassName TokenFilter
     * @Desc TODO   请求认证过滤器
     * @Date 2019/6/29 17:49
     * @Version 1.0
     */
    public class TokenFilter implements GlobalFilter{
     
        @Override
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            // 请求对象
            ServerHttpRequest request = exchange.getRequest();
            // 响应对象
            ServerHttpResponse response = exchange.getResponse();
     
            // 只有综合路由才添加这个全局过滤器(routesId:route_all)
            // 如果请求路径中不存在 routeAll 字符串
            if(request.getURI().toString().indexOf("routeAll") == -1){
                System.out.println("filter -> return");
                // 直接跳出
                return chain.filter(exchange);
            }
     
            // 从请求中获取 token 参数
            String token = exchange.getRequest().getQueryParams().getFirst("token");
            // 如果为空,那么将返回 401
            if (token == null || token.isEmpty()) {
     
                // 响应消息内容对象
                JSONObject message = new JSONObject();
                // 响应状态
                message.put("code", -1);
                // 响应内容
                message.put("msg", "缺少凭证");
                // 转换响应消息内容对象为字节
                byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
                DataBuffer buffer = response.bufferFactory().wrap(bits);
                // 设置响应对象状态码 401
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                // 设置响应对象内容并且指定编码,否则在浏览器中会中文乱码
                response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
                // 返回响应对象
                return response.writeWith(Mono.just(buffer));
            }
            // 获取请求地址
            String beforePath = request.getPath().pathWithinApplication().value();
            // 获取响应状态码
            HttpStatus beforeStatusCode = response.getStatusCode();
            System.out.println("响应码:" + beforeStatusCode + ",请求路径:" + beforePath);
            // 请求前
            System.out.println("filter -> before");
            // 如果不为空,就通过
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                // 获取请求地址
                String afterPath = request.getPath().pathWithinApplication().value();
                // 获取响应状态码
                HttpStatus afterStatusCode = response.getStatusCode();
                System.out.println("响应码:" + afterStatusCode + ",请求路径:" + afterPath);
                // 响应后
                System.out.println("filter -> after");
            }));
        }
     
    }

      8. 全局过滤器,不需要配置在配置文件中,作用于所有路由;只是这里在处理前做了判断,只有路径中存在

          routeAll 字符串才到后续处理;并且处理分为请求前的处理,和响应后的处理

      9. 此时在地址:http://localhost:8000/all/routeAll 中添加 token 参数

     10. 访问:http://localhost:8000/all/routeAll?token=123

     11. 轮流输出内容:'Can I pass? yes! port:9000' 和 'Can I pass? yes! port:9001'

     12. 观察 gateway 工程的控制台,会有如下内容输出

    响应码:null,请求路径:/routeAll
    filter -> before
    响应码:200,请求路径:/routeAll
    filter -> after

    13. 证明全局过滤器过滤成功

    service 工程 - 项目结构

    把多工程项目使用 IntelliJ IDEA 打开

    • 把项目从 GitHub 中下载到你的本地
    • 打开 IntelliJ IDEA 
    • 点击 File -> Open
    • 打开你下载到本地的项目目录
    • springcloud-gateway -> springcloud-gateway-service(选择打开此工程)
    • 打开 service 工程后
    • 再次点击 File -> Project Structrue
    • 选择 Modules,点击 '+' 符号
    • 点击 Import  Module
    • 还是打开你下载到本地的项目目录
    • springcloud-gateway -> springcloud-gateway-commons -> pom.xml
    • 点击 OK
    • 点击 Next,Finish
    • 点击 Apply,OK

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

     

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    master-service - 限流(重点,解决不生效问题)

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————

    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    ————————————————
    版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

    开发工具IntelliJ IDEA正文commons 工程commons 工程 - POM 文件<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>     <!-- 三坐标 -->    <groupId>com.zwc</groupId>    <artifactId>springcloud-gateway-commons</artifactId>    <version>1.0</version>     <!-- 工程名称和描述 -->    <name>springcloud-gateway-commons</name>    <description>公用工程</description>     <!-- 打包方式 -->    <packaging>jar</packaging>     <!-- 在 properties 下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->    <properties>        <!-- 编码 -->        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <!-- jdk -->        <java.version>1.8</java.version>         <!-- SpringBoot -->        <platform-bom.version>Cairo-SR3</platform-bom.version>         <!-- SpringCloud -->        <spring-cloud-dependencies.version>Finchley.RELEASE</spring-cloud-dependencies.version>    </properties>     <!-- 加入依赖 -->    <dependencies>     </dependencies>     <!-- 依赖 jar 包版本管理的管理器 -->    <!-- 如果 dependencies 里的 dependency 自己没有声明 version 元素,那么 maven 就此处来找版本声明。 -->    <!-- 如果有,就会继承它;如果没有就会报错,告诉你没有版本信息 -->    <!-- 优先级:如果 dependencies 里的 dependency 已经声明了版本信息,就不会生效此处的版本信息了 -->    <dependencyManagement>        <dependencies>            <!-- SpringBoot -->            <dependency>                <groupId>io.spring.platform</groupId>                <artifactId>platform-bom</artifactId>                <version>${platform-bom.version}</version>                <type>pom</type>                <scope>import</scope>            </dependency>            <!-- SpringCloud -->            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>${spring-cloud-dependencies.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>配置一些共用依赖commons 工程 - 项目结构

     
    service 工程  ① 此工程下有四个模块:一个注册中心,一个网关以及两个提供者
      ② 两个提供者除端口不一致以外,其他代码基本一致
     
    registry-service(注册中心)registry-service - POM 文件<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>     <!-- 继承父 -->    <parent>        <groupId>com.zwc</groupId>        <artifactId>springcloud-gateway-service</artifactId>        <version>1.0</version>    </parent>     <!-- 三坐标 -->    <groupId>com.zwc</groupId>    <artifactId>springcloud-gateway-registry-service</artifactId>    <version>1.0</version>     <!-- 工程名称描述 -->    <name>springcloud-gateway-registry-service</name>    <description>注册中心</description>     <!-- 打包方式 -->    <packaging>jar</packaging>     <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->    <properties>     </properties>     <!-- 加入依赖 -->    <dependencies>        <!-- 服务注册中心 -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>        </dependency>    </dependencies>     <!-- 插件依赖 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build> </project>主要加入 spring-cloud-starter-netflix-eureka-server 依赖registry-service - application.yml 配置文件# 端口server:  port: 8761 # 应用名称spring:  application:    name: eureka-server eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    # 是否向注册中心注册自己    registerWithEureka: false    # 是否向注册中心获取注册信息    fetchRegistry: false    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/这里使用了默认的 8761 端口,当然也可以更改,不过在发现调用服务端的注册中心地址端口要与它一致registry-service - 启动类package com.zwc; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication@EnableEurekaServerpublic class SpringcloudGatewayRegistryServiceApplication {     public static void main(String[] args) {        SpringApplication.run(SpringcloudGatewayRegistryServiceApplication.class, args);    } }在启动类中添加 @EnableEurekaServer 注解表示此工程是注册中心registry-service - 启动项目  1. 项目启动成功后访问 http://localhost:8761/ 即可看到 eureka-server 主页面


     
      注:由于服务工程 A 和服务工程 B 除端口不一致以外,其他代码基本一致,所以服务工程 B 不再赘述
    a-service(服务工程 A)a-service - POM 文件<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>     <!-- 继承父 -->    <parent>        <groupId>com.zwc</groupId>        <artifactId>springcloud-gateway-a-service</artifactId>        <version>1.0</version>    </parent>     <!-- 三坐标 -->    <groupId>com.zwc</groupId>    <artifactId>springcloud-gateway-a-service-core</artifactId>    <version>1.0</version>     <!-- 工程名称描述 -->    <name>springcloud-gateway-a-service-core</name>    <description>服务工程 - A 核心</description>     <!-- 打包方式 -->    <packaging>jar</packaging>     <!-- 在 properties下声明相应的版本信息,然后在dependency下引用的时候用 ${} 就可以引入该版本jar包了 -->    <properties>     </properties>     <!-- 加入依赖 -->    <dependencies>        <!-- commons工程 依赖 -->        <dependency>            <groupId>com.zwc</groupId>            <artifactId>springcloud-gateway-commons</artifactId>            <version>1.0</version>        </dependency>         <!-- api工程 依赖 -->        <dependency>            <groupId>com.zwc</groupId>            <artifactId>springcloud-gateway-a-service-api</artifactId>            <version>1.0</version>        </dependency>         <!-- springboot web 依赖 -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-web</artifactId>        </dependency>         <!-- 提供者消费者 -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>    </dependencies>     <!-- 插件依赖 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build> </project>加入 spring-cloud-starter-netflix-eureka-client 依赖a-service - application.yml 配置文件# 端口server:  port: 9000 # 应用名称spring:  application:    name: gateway-service eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/注意此处配置注册中心地址的端口为 8761 也就是上面注册中心工程配置的端口a-service - controller 前端控制器(提供服务)package com.zwc.a.controller; import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /* * @ClassName ASayHelloController * @Desc TODO   Say Hello * @Date 2019/5/20 23:24 * @Version 1.0 */@RestControllerpublic class ASayHelloController {     /*     * @ClassName ASayHelloController     * @Desc TODO   读取配置文件中的端口     * @Date 2019/5/20 23:24     * @Version 1.0     */    @Value("${server.port}")    private String port;     /*     * @ClassName ASayHelloController     * @Desc TODO   Say Hello     * @Date 2019/5/20 23:24     * @Version 1.0     */    @RequestMapping("/hello")    public String hello(){        return "Hello!I'm a. port:" + port;    }     /*     * @ClassName ASayHelloController     * @Desc TODO   接收从网关传入的参数     * @Date 2019/6/23 16:28     * @Version 1.0     */    @RequestMapping("/name")    public String name(String name){        return "My name is " + name + ". aaa";    }     /*     * @ClassName ASayHelloController     * @Desc TODO   接收从网关传入的参数     * @Date 2019/6/23 16:52     * @Version 1.0     */    @RequestMapping("/age")    public String age(String age){        return "I am " + age + " years old this year. aaa";    }     /*     * @ClassName ASayHelloController     * @Desc TODO   接收从网关传入的参数     * @Date 2019/6/29 22:00     * @Version 1.0     */    @RequestMapping("/routeAll")    public String routeAll(String pass) {        return "Can I pass? " + pass + "! port:" + port;    } }提供输出字符串服务,供网关调用a-service - 启动类package com.zwc; import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication@EnableEurekaClientpublic class SpringcloudGatewayAServiceCoreApplication {     public static void main(String[] args) {        SpringApplication.run(SpringcloudGatewayAServiceCoreApplication.class, args);    } }添加 @EnableEurekaClient 注解表示此工程可以向注册中心提供服务a-service - 启动项目  1. 刷新 http://localhost:8761/(注册中心)可以看到服务已经被注册进来了


      2. 项目启动成功后访问:http://localhost:9000/hello
      3. 输出内容:'Hello!I'm a. port:9000'
      4. 同样启动服务工程 B后,刷新 http://localhost:8761/(注册中心)


      5. 项目启动成功后访问:http://localhost:9001/hello
      6. 输出内容:'Hello!I'm b. port:9001'
      7. 其他接口是下面网关服务启动后转发调用的,也是本博客的重头戏
     
    master-service(网关)master-service - POM 文件<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>     <!-- 继承父 -->    <parent>        <groupId>com.zwc</groupId>        <artifactId>springcloud-gateway-service</artifactId>        <version>1.0</version>    </parent>     <!-- 三坐标 -->    <groupId>com.zwc</groupId>    <artifactId>springcloud-gateway-master-service</artifactId>    <version>1.0</version>     <!-- 工程名称描述 -->    <name>springcloud-gateway-master-service</name>    <description>Spring Cloud Gateway 服务网关</description>     <!-- 打包方式 -->    <packaging>jar</packaging>     <!-- 在 properties下声明相应的版本信息,然后在 dependency 下引用的时候用 ${} 就可以引入该版本 jar 包了 -->    <properties>        <!-- ali json -->        <fastjson.version>1.2.47</fastjson.version>    </properties>     <!-- 加入依赖 -->    <dependencies>        <!-- 提供者消费者 -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>        </dependency>         <!-- gateway -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-gateway</artifactId>        </dependency>         <!-- redis -->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>        </dependency>         <!-- hystrix -->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>        </dependency>         <!-- ali json依赖 -->        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>${fastjson.version}</version>        </dependency>    </dependencies>     <!-- 插件依赖 -->    <build>        <plugins>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>            </plugin>        </plugins>    </build> </project>加入 spring-cloud-starter-netflix-eureka-client 依赖:提供和注册服务加入 spring-cloud-starter-gateway 依赖:gateway加入 spring-boot-starter-data-redis-reactive 依赖:结合 Redis 限流加入 spring-cloud-starter-netflix-hystrix 依赖:熔断器master-service - application.yml 配置文件# 端口server:  port: 8000 spring:  profiles:    # 指定配置    # route_simple:简单尝试    # route_stripPrefix:截取请求    # route_uri:转发指定地址并传入参数    # route_addRequestParameter:转发指定服务并传入参数    # route_hystrix:熔断    # route_requestRateLimiter:限流    # route_all:综合    active: route_simple --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 简单尝试  profiles: route_simple  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   简单尝试      - id: route_simple        # 目标服务地址(uri:地址,请求转发后的地址)        uri: https://www.zouwencong.com        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/archive        - Path=/archive eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 截取请求  profiles: route_stripPrefix  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   截取请求      - id: route_simple        # 目标服务地址(uri:地址,请求转发后的地址)        uri: https://www.zouwencong.com        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉        - Path=/str/archive        filters:        ## 截取路径位数        - StripPrefix=1 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 转发指定地址并传入参数  profiles: route_uri  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数      - id: route_uri        # 目标服务地址(uri:地址,请求转发后的地址)        uri: http://localhost:9000        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=name, zwc eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 转发指定服务并传入参数  profiles: route_addRequestParameter  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数      - id: route_addRequestParameter        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 熔断  profiles: route_hystrix  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   熔断      - id: route_hystrix        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three        ## 熔断        - name: Hystrix          args:            name: fallbackcmd            ### fallback 时调用的方法 http://localhost:8000/fallback            fallbackUri: forward:/fallback eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 限流  profiles: route_requestRateLimiter  redis:    host: localhost    port: 6379    database: 0  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   限流      - id: route_requestRateLimiter        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three        ## 限流        - name: RequestRateLimiter          args:            ### 限流过滤器的 Bean 名称            key-resolver: '#{@uriKeyResolver}'            ### 希望允许用户每秒处理多少个请求            redis-rate-limiter.replenishRate: 1            ### 用户允许在一秒钟内完成的最大请求数            redis-rate-limiter.burstCapacity: 3 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug --- spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 综合  profiles: route_all  redis:    host: localhost    port: 6379    database: 0  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   综合      - id: route_all        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉        - Path=/all/routeAll        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 截取路径位数        - StripPrefix=1        ## 添加指定参数        - AddRequestParameter=pass, yes        ## 熔断        - name: Hystrix          args:            name: fallbackcmd            ### fallback 时调用的方法 http://localhost:8000/fallback            fallbackUri: forward:/fallback        ## 限流        - name: RequestRateLimiter          args:            ### 限流过滤器的 Bean 名称            key-resolver: '#{@uriKeyResolver}'            ### 希望允许用户每秒处理多少个请求            redis-rate-limiter.replenishRate: 1            ### 用户允许在一秒钟内完成的最大请求数            redis-rate-limiter.burstCapacity: 3 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug注意配置注册中心地址的端口都为 8761 也就是上面注册中心工程配置的端口每一对 '---' 符号中的配置文件都是单独的,使用 spring.profiles.active 指定每一对 '---' 符号中的配置文件都只配置了一个 route(路由)route(路由)由四部分组成,其中 filters 不是必须参数唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters) 
    master-service - 简单尝试spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 简单尝试  profiles: route_simple  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   简单尝试      - id: route_simple        # 目标服务地址(uri:地址,请求转发后的地址)        uri: https://www.zouwencong.com        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/archive        - Path=/archive  1. 停止注册中心工程(registry-service)、服务工程 A 和服务工程 B
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_simple
      3. 上面配置文件内容意思是当访问 http://localhost:8000/archive (网关地址/archive)
          会被转发到 https://www.zouwencong.com/archive/ (uri/archive)
      4. 启动注册中心工程(registry-service)和网关工程(master-service)
      5. 项目启动成功后访问:http://localhost:8000/archive
      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/
      7. 证明服务转发成功
     
    master-service - 截取请求spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 截取请求  profiles: route_stripPrefix  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   截取请求      - id: route_simple        # 目标服务地址(uri:地址,请求转发后的地址)        uri: https://www.zouwencong.com        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/archive,/str 部分会被下面的过滤器给截取掉        - Path=/str/archive        filters:        ## 截取路径位数        - StripPrefix=1 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service)和网关工程(master-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_stripPrefix
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/str/archive (网关地址/str/archive)截取 /str 部分,
          截取后被转发到 https://www.zouwencong.com/archive/ (uri/archive)
      4. 启动注册中心工程(registry-service)和网关工程(master-service)
      5. 项目启动成功后访问:http://localhost:8000/str/archive
      6. 发现页面会自动被跳转到:https://www.zouwencong.com/archive/
      7. 证明路径被截取并服务转发成功
     
    master-service - 转发指定地址并传入参数spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 转发指定地址并传入参数  profiles: route_uri  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数      - id: route_uri        # 目标服务地址(uri:地址,请求转发后的地址)        uri: http://localhost:9000        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=name, zwc eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service)和网关工程(master-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_uri
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/name (网关地址/name)
          会被转发到 http://localhost:9000/name(uri/name),并传入 'name=zwc' 参数(注意为 Get 请求)
      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)
      5. 项目启动成功后访问:http://localhost:8000/name
      6. 输出内容:'My name is zwc. aaa'(通过网关转发的参数有值)
      7. 打开新页面访问:http://localhost:9000/name
      8. 输出内容:'My name is null. aaa'(问的直接访参数没有值)
      9. 证明转发指定地址并传入参数成功
     
    master-service - 转发指定服务并传入参数spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 转发指定服务并传入参数  profiles: route_addRequestParameter  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   转发指定服务并传入参数      - id: route_addRequestParameter        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A(a-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值
          更改为 route_addRequestParameter
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)
          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)
      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足
          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册
          服务名。
      5. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      6. 项目启动成功后访问:http://localhost:8000/age
      7. 这时可能会报错 500.错误信息为 'Unable to find instance for gateway-service'
      8. 这种情况不要慌张,只是服务还没有被注册到注册中心,稍等片刻再访问
      9. 多次访问:http://localhost:8000/age
     10. 轮流输出内容:'I am three years old this year. aaa' 和 'I am three years old this year. bbb'
     11. 此时还通过网关达到了负载均衡的效果
     12. 证明转发指定服务并传入参数成功
     
    master-service - 熔断spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 熔断  profiles: route_hystrix  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   熔断      - id: route_hystrix        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three        ## 熔断        - name: Hystrix          args:            name: fallbackcmd            ### fallback 时调用的方法 http://localhost:8000/fallback            fallbackUri: forward:/fallback eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_hystrix
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)
          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)
      4. 注意此处的配置 uri: lb://gateway-service 与之前都有所不同,之前都是指定了明确的转发地址,可以满足
          单个服务转发的需求,但是一般情况都会有多个服务,所以这里是指定的服务名称,格式为:lb://应用注册
          服务名。
      5. 此处还多配置了一个过滤器 '- name: Hystrix'(熔断)
      6. 当请求服务出错时,会调用 fallback,路径为:http://localhost:8000/fallback (网关地址/fallback)
      7. 此时就需要如下前端控制器
    master-service - 熔断 - controllerpackage com.zwc.gateway.hystrix; import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController; /** * @ClassName FallbackController * @Desc TODO   网关断路器 * @Date 2019/6/23 19:33 * @Version 1.0 */@RestControllerpublic class FallbackController {     /*     * @ClassName FallbackController     * @Desc TODO   网关断路器     * @Date 2019/6/23 19:35     * @Version 1.0     */    @RequestMapping("/fallback")    public String fallback() {        return "I'm Spring Cloud Gateway fallback.";    } }  7. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      8. 项目启动成功后访问:http://localhost:8000/age
      9. 输出内容:'I'm Spring Cloud Gateway fallback.'
     10. 证明熔断成功
     
    master-service - 限流(重点,解决不生效问题)spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 限流  profiles: route_requestRateLimiter  redis:    host: localhost    port: 6379    database: 0  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   限流      - id: route_requestRateLimiter        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 添加指定参数        - AddRequestParameter=age, three        ## 限流        - name: RequestRateLimiter          args:            ### 限流过滤器的 Bean 名称            key-resolver: '#{@uriKeyResolver}'            ### 希望允许用户每秒处理多少个请求            redis-rate-limiter.replenishRate: 1            ### 用户允许在一秒钟内完成的最大请求数            redis-rate-limiter.burstCapacity: 3 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值
          更改为 route_requestRateLimiter
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/age (网关地址/age)
          会被转发到 http://gateway-service/age(uri/age),并传入 'age=three' 参数(注意为 Get 请求)
      4. 注意此处还需要配置 redis 的连接信息
      5. 注意此处是结合 redis 实现的限流,所以 filter 过滤器的 name 必须为 RequestRateLimiter
      6. 并且通过实现 KeyResolver 类来自定义限流策略,如下
    master-service - 限流 - 策略package com.zwc.gateway.config.filters; import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono; /** * @ClassName UriKeyResolver * @Desc TODO   Spring Cloud Gateway 网关限流过滤器 * @Date 2019/6/23 17:59 * @Version 1.0 */public class UriKeyResolver implements KeyResolver {     /*     * @ClassName UriKeyResolver     * @Desc TODO   根据请求的 uri 限流     * @Date 2019/6/29 17:25     * @Version 1.0     */    @Override    public Mono<String> resolve(ServerWebExchange exchange) {        return Mono.just(exchange.getRequest().getURI().getPath());    } }  7. 启动本地 redis(redis-server.exe) 服务
      8. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      9. 项目启动成功后访问:http://localhost:8000/age
      9. 此时限流却无论如何都不生效,原因有如下两点
    ① redis-server 版本过低!我 Windows 本地是 redis-2.4.2 版本的,要用 3 以上的版本!!!
    ② 数据在 redis 中存储的时间只有几秒,所以得使用 monitor 指令来动态的观察!!!
     10. 打开 redis-cli.exe,输入命令 monitor 
     11. 快速刷新地址:http://localhost:8000/age
     12. 页面上会出现 429,redis-cli.exe 中会出现很多数据交互(request_rate_limiter.xxx 开头的 key)
     13. 证明限流成功
     
    master-service - 综合spring:  # 配置文件名称,用来标识不同环境的配置。由 spring.profiles.active 的值来决定使用哪组配置。  ## 综合  profiles: route_all  redis:    host: localhost    port: 6379    database: 0  application:    # 应用名称    name: gateway-master  cloud:    gateway:      discovery:        locator:          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务          enabled: true      # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)      routes:      # 路由标识(id:标识,具有唯一性)   综合      - id: route_all        # 目标服务地址(uri:地址,请求转发后的地址)        uri: lb://gateway-service        # 路由条件(predicates:断言,匹配 HTTP 请求内容)        predicates:        ## 转发地址格式为 uri/routeAll,/all 部分会被下面的过滤器给截取掉        - Path=/all/routeAll        ## 匹配 GET 请求        - Method=GET        # 过滤器(filters:过滤器,过滤规则)        filters:        ## 截取路径位数        - StripPrefix=1        ## 添加指定参数        - AddRequestParameter=pass, yes        ## 熔断        - name: Hystrix          args:            name: fallbackcmd            ### fallback 时调用的方法 http://localhost:8000/fallback            fallbackUri: forward:/fallback        ## 限流        - name: RequestRateLimiter          args:            ### 限流过滤器的 Bean 名称            key-resolver: '#{@uriKeyResolver}'            ### 希望允许用户每秒处理多少个请求            redis-rate-limiter.replenishRate: 1            ### 用户允许在一秒钟内完成的最大请求数            redis-rate-limiter.burstCapacity: 3 eureka:  instance:    # 使用 ip 代替实例名    prefer-ip-address: true    # 实例的主机名    hostname: ${spring.cloud.client.ip-address}    # 实例的 ID 规则    instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}  client:    serviceUrl:      # 注册中心地址      defaultZone: http://${eureka.instance.hostname}:8761/eureka/ logging:  level:    # log 级别    org.springframework.cloud.gateway: debug  1. 停止注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      2. 把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改为 route_all
      3. 上面配置文件内容意思是访问的路径 http://localhost:8000/all/routeAll (网关地址/all/routeAll)截取 /all 部分,
          会被转发到 http://gateway-service/routeAll(uri/routeAll),并传入 'pass=yes' 参数(注意为 Get 请求)
      4. 启动注册中心工程(registry-service),网关工程(master-service)和服务工程 A/B(a-service、b-service)
      5. 项目启动成功后访问:http://localhost:8000/all/routeAll
      6. 首先会返回 'I'm Spring Cloud Gateway fallback.',因为服务还未被注册到注册中心
      7. 然后会返回 '{"msg":"缺少凭证","code":-1}',因为配置了全局过滤器,如下
    package com.zwc.gateway.config.filters; import com.alibaba.fastjson.JSONObject;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.core.Ordered;import org.springframework.http.HttpStatus;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;import org.springframework.core.io.buffer.DataBuffer; import java.net.InetSocketAddress;import java.nio.charset.StandardCharsets; /** * @ClassName TokenFilter * @Desc TODO   请求认证过滤器 * @Date 2019/6/29 17:49 * @Version 1.0 */public class TokenFilter implements GlobalFilter{     @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        // 请求对象        ServerHttpRequest request = exchange.getRequest();        // 响应对象        ServerHttpResponse response = exchange.getResponse();         // 只有综合路由才添加这个全局过滤器(routesId:route_all)        // 如果请求路径中不存在 routeAll 字符串        if(request.getURI().toString().indexOf("routeAll") == -1){            System.out.println("filter -> return");            // 直接跳出            return chain.filter(exchange);        }         // 从请求中获取 token 参数        String token = exchange.getRequest().getQueryParams().getFirst("token");        // 如果为空,那么将返回 401        if (token == null || token.isEmpty()) {             // 响应消息内容对象            JSONObject message = new JSONObject();            // 响应状态            message.put("code", -1);            // 响应内容            message.put("msg", "缺少凭证");            // 转换响应消息内容对象为字节            byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);            DataBuffer buffer = response.bufferFactory().wrap(bits);            // 设置响应对象状态码 401            response.setStatusCode(HttpStatus.UNAUTHORIZED);            // 设置响应对象内容并且指定编码,否则在浏览器中会中文乱码            response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");            // 返回响应对象            return response.writeWith(Mono.just(buffer));        }        // 获取请求地址        String beforePath = request.getPath().pathWithinApplication().value();        // 获取响应状态码        HttpStatus beforeStatusCode = response.getStatusCode();        System.out.println("响应码:" + beforeStatusCode + ",请求路径:" + beforePath);        // 请求前        System.out.println("filter -> before");        // 如果不为空,就通过        return chain.filter(exchange).then(Mono.fromRunnable(() -> {            // 获取请求地址            String afterPath = request.getPath().pathWithinApplication().value();            // 获取响应状态码            HttpStatus afterStatusCode = response.getStatusCode();            System.out.println("响应码:" + afterStatusCode + ",请求路径:" + afterPath);            // 响应后            System.out.println("filter -> after");        }));    } }  8. 全局过滤器,不需要配置在配置文件中,作用于所有路由;只是这里在处理前做了判断,只有路径中存在
          routeAll 字符串才到后续处理;并且处理分为请求前的处理,和响应后的处理
      9. 此时在地址:http://localhost:8000/all/routeAll 中添加 token 参数
     10. 访问:http://localhost:8000/all/routeAll?token=123
     11. 轮流输出内容:'Can I pass? yes! port:9000' 和 'Can I pass? yes! port:9001'
     12. 观察 gateway 工程的控制台,会有如下内容输出
    响应码:null,请求路径:/routeAllfilter -> before响应码:200,请求路径:/routeAllfilter -> after 13. 证明全局过滤器过滤成功
     
    service 工程 - 项目结构

     
    把多工程项目使用 IntelliJ IDEA 打开把项目从 GitHub 中下载到你的本地打开 IntelliJ IDEA 点击 File -> Open打开你下载到本地的项目目录springcloud-gateway -> springcloud-gateway-service(选择打开此工程)打开 service 工程后再次点击 File -> Project Structrue选择 Modules,点击 '+' 符号点击 Import  Module还是打开你下载到本地的项目目录springcloud-gateway -> springcloud-gateway-commons -> pom.xml点击 OK点击 Next,Finish点击 Apply,OK 
     
    希望能够帮助到你
    o————————————————版权声明:本文为CSDN博主「intomylife」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/qq_41402200/article/details/94333830

  • 相关阅读:
    根据表生成接收(zml)
    删除指定日期,指定设备的排产记录(zml)
    1029 Median
    1027 Colors in Mars (20 分)进制转换
    1028 List Sorting 排序
    1025 PAT Ranking
    1024 Palindromic Number(大数加法)
    1023 Have Fun with Numbers
    1022 Digital Library
    逆序打印乘法表
  • 原文地址:https://www.cnblogs.com/telwanggs/p/12485784.html
Copyright © 2020-2023  润新知