原文網址 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