(轉)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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM