前言
SpringCloud 是微服務(wù)中的翹楚喂走,最佳的落地方案。
Spring Cloud Gateway 是 Spring Cloud 新推出的網(wǎng)關(guān)框架奇适,之前是 Netflix Zuul渔嚷。網(wǎng)關(guān)通常在項(xiàng)目中為了簡(jiǎn)化
前端的調(diào)用邏輯,同時(shí)也簡(jiǎn)化內(nèi)部服務(wù)之間互相調(diào)用的復(fù)雜度绽快;具體作用就是轉(zhuǎn)發(fā)服務(wù)芥丧,接收并轉(zhuǎn)發(fā)所有內(nèi)外
部的客戶端調(diào)用;其他常見(jiàn)的功能還有權(quán)限認(rèn)證坊罢,限流控制等等娄柳。
本博客會(huì)提到網(wǎng)關(guān)的基本轉(zhuǎn)發(fā)功能,熔斷功能艘绍,限流功能以及功能的綜合使用赤拒。
2021年Java真題面試文檔分享給大家,下面是一張springcloud的技術(shù)點(diǎn)整理:
源碼
GitHub地址:https://github.com/intomylife/SpringCloud
環(huán)境
JDK 1.8.0 +
Maven 3.0 +
SpringBoot 2.0.3
SpringCloud Finchley.RELEASE
Redis 3.0 +
開(kāi)發(fā)工具
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>
<!-- 三坐標(biāo) -->
<groupId>com.zwc</groupId>
<artifactId>springcloud-gateway-commons</artifactId>
<version>1.0</version>
<!-- 工程名稱和描述 -->
<name>springcloud-gateway-commons</name>
<description>公用工程</description>
<!-- 打包方式 -->
<packaging>jar</packaging>
<!-- 在 properties 下聲明相應(yīng)的版本信息诱鞠,然后在 dependency 下引用的時(shí)候用 ${} 就可以引入該版本 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 自己沒(méi)有聲明 version 元素挎挖,那么 maven 就此處來(lái)找版本聲明。 -->
<!-- 如果有航夺,就會(huì)繼承它蕉朵;如果沒(méi)有就會(huì)報(bào)錯(cuò),告訴你沒(méi)有版本信息 -->
<!-- 優(yōu)先級(jí):如果 dependencies 里的 dependency 已經(jīng)聲明了版本信息阳掐,就不會(huì)生效此處的版本信息了 -->
<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 工程 - 項(xiàng)目結(jié)構(gòu)
service 工程
**① 此工程下有四個(gè)模塊:一個(gè)注冊(cè)中心始衅,一個(gè)網(wǎng)關(guān)以及兩個(gè)提供者
② 兩個(gè)提供者除端口不一致以外,其他代碼基本一致
registry-service(注冊(cè)中心)
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>
<!-- 三坐標(biāo) -->
<groupId>com.zwc</groupId>
<artifactId>springcloud-gateway-registry-service</artifactId>
<version>1.0</version>
<!-- 工程名稱描述 -->
<name>springcloud-gateway-registry-service</name>
<description>注冊(cè)中心</description>
<!-- 打包方式 -->
<packaging>jar</packaging>
<!-- 在 properties下聲明相應(yīng)的版本信息缭保,然后在dependency下引用的時(shí)候用 ${} 就可以引入該版本jar包了 -->
<properties>
</properties>
<!-- 加入依賴 -->
<dependencies>
<!-- 服務(wù)注冊(cè)中心 -->
<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
#應(yīng)用名稱
spring:
application:
name: eureka-server
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
# 是否向注冊(cè)中心注冊(cè)自己
registerWithEureka: false
# 是否向注冊(cè)中心獲取注冊(cè)信息
fetchRegistry: false
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
這里使用了默認(rèn)的 8761 端口汛闸,當(dāng)然也可以更改,不過(guò)在發(fā)現(xiàn)調(diào)用服務(wù)端的注冊(cè)中心地址端口要與它一致
registry-service - 啟動(dòng)類
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);
}
}
在啟動(dòng)類中添加 @EnableEurekaServer 注解表示此工程是注冊(cè)中心
registry-service - 啟動(dòng)項(xiàng)目
- 項(xiàng)目啟動(dòng)成功后訪問(wèn) http://localhost:8761/ 即可看到 eureka-server 主頁(yè)面
image
注:由于服務(wù)工程 A 和服務(wù)工程 B 除端口不一致以外艺骂,其他代碼基本一致诸老,所以服務(wù)工程 B 不再贅述
a-service(服務(wù)工程 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>
<!-- 三坐標(biāo) -->
<groupId>com.zwc</groupId>
<artifactId>springcloud-gateway-a-service-core</artifactId>
<version>1.0</version>
<!-- 工程名稱描述 -->
<name>springcloud-gateway-a-service-core</name>
<description>服務(wù)工程 - A 核心</description>
<!-- 打包方式 -->
<packaging>jar</packaging>
<!-- 在 properties下聲明相應(yīng)的版本信息,然后在dependency下引用的時(shí)候用 ${} 就可以引入該版本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>
<!-- 提供者消費(fèi)者 -->
<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
#應(yīng)用名稱
spring:
application:
name: gateway-service
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
注意此處配置注冊(cè)中心地址的端口為 8761 也就是上面注冊(cè)中心工程配置的端口
a-service - controller 前端控制器(提供服務(wù))
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 接收從網(wǎng)關(guān)傳入的參數(shù)
* @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 接收從網(wǎng)關(guān)傳入的參數(shù)
* @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 接收從網(wǎng)關(guān)傳入的參數(shù)
* @Date 2019/6/29 22:00
* @Version 1.0
*/
@RequestMapping("/routeAll")
public String routeAll(String pass) {
return "Can I pass? " + pass + "! port:" + port;
}
}
提供輸出字符串服務(wù)别伏,供網(wǎng)關(guān)調(diào)用
a-service - 啟動(dòng)類
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 注解表示此工程可以向注冊(cè)中心提供服務(wù)
a-service - 啟動(dòng)項(xiàng)目
- 刷新 http://localhost:8761/(注冊(cè)中心)可以看到服務(wù)已經(jīng)被注冊(cè)進(jìn)來(lái)了
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:9000/hello
輸出內(nèi)容:'Hello!I'm a. port:9000'
同樣啟動(dòng)服務(wù)工程 B后忧额,刷新 http://localhost:8761/(注冊(cè)中心)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:9001/hello
輸出內(nèi)容:'Hello厘肮!I'm b. port:9001'
其他接口是下面網(wǎng)關(guān)服務(wù)啟動(dòng)后轉(zhuǎn)發(fā)調(diào)用的,也是本博客的重頭戲
master-service(網(wǎng)關(guān))
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>
<!-- 三坐標(biāo) -->
<groupId>com.zwc</groupId>
<artifactId>springcloud-gateway-master-service</artifactId>
<version>1.0</version>
<!-- 工程名稱描述 -->
<name>springcloud-gateway-master-service</name>
<description>Spring Cloud Gateway 服務(wù)網(wǎng)關(guān)</description>
<!-- 打包方式 -->
<packaging>jar</packaging>
<!-- 在 properties下聲明相應(yīng)的版本信息睦番,然后在 dependency 下引用的時(shí)候用 ${} 就可以引入該版本 jar 包了 -->
<properties>
<!-- ali json -->
<fastjson.version>1.2.47</fastjson.version>
</properties>
<!-- 加入依賴 -->
<dependencies>
<!-- 提供者消費(fèi)者 -->
<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 依賴:提供和注冊(cè)服務(wù)
加入spring-cloud-starter-gateway 依賴:gateway
加入spring-boot-starter-data-redis-reactive 依賴:結(jié)合 Redis 限流
加入spring-cloud-starter-netflix-hystrix 依賴:熔斷器
master-service - application.yml 配置文件
#端口
server:
port: 8000
spring:
profiles:
# 指定配置
# route_simple:簡(jiǎn)單嘗試
# route_stripPrefix:截取請(qǐng)求
# route_uri:轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
# route_addRequestParameter:轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
# route_hystrix:熔斷
# route_requestRateLimiter:限流
# route_all:綜合
active: route_simple
---
spring:
# 配置文件名稱类茂,用來(lái)標(biāo)識(shí)不同環(huán)境的配置。由 spring.profiles.active 的值來(lái)決定使用哪組配置抡砂。
## 簡(jiǎn)單嘗試
profiles: route_simple
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合大咱,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由,它由唯一標(biāo)識(shí)(ID)注益、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)溯捆。filters 不是必需參數(shù)丑搔。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)厦瓢,具有唯一性) 簡(jiǎn)單嘗試
- id: route_simple
# 目標(biāo)服務(wù)地址(uri:地址,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: https://www.zouwencong.com
# 路由條件(predicates:斷言啤月,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/archive
- Path=/archive
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱煮仇,用來(lái)標(biāo)識(shí)不同環(huán)境的配置。由 spring.profiles.active 的值來(lái)決定使用哪組配置谎仲。
## 截取請(qǐng)求
profiles: route_stripPrefix
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合浙垫,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由,它由唯一標(biāo)識(shí)(ID)郑诺、目標(biāo)服務(wù)地址(uri)夹姥、一組斷言(predicates)和一組過(guò)濾器組成(filters)。filters 不是必需參數(shù)辙诞。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)辙售,具有唯一性) 截取請(qǐng)求
- id: route_simple
# 目標(biāo)服務(wù)地址(uri:地址,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: https://www.zouwencong.com
# 路由條件(predicates:斷言飞涂,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/archive旦部,/str 部分會(huì)被下面的過(guò)濾器給截取掉
- Path=/str/archive
filters:
## 截取路徑位數(shù)
- StripPrefix=1
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置较店。由 spring.profiles.active 的值來(lái)決定使用哪組配置士八。
## 轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
profiles: route_uri
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由梁呈,它由唯一標(biāo)識(shí)(ID)曹铃、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)捧杉。filters 不是必需參數(shù)陕见。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
- id: route_uri
# 目標(biāo)服務(wù)地址(uri:地址味抖,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: http://localhost:9000
# 路由條件(predicates:斷言评甜,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=name, zwc
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱仔涩,用來(lái)標(biāo)識(shí)不同環(huán)境的配置忍坷。由 spring.profiles.active 的值來(lái)決定使用哪組配置。
## 轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
profiles: route_addRequestParameter
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合熔脂,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由佩研,它由唯一標(biāo)識(shí)(ID)、目標(biāo)服務(wù)地址(uri)霞揉、一組斷言(predicates)和一組過(guò)濾器組成(filters)旬薯。filters 不是必需參數(shù)。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)适秩,具有唯一性) 轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
- id: route_addRequestParameter
# 目標(biāo)服務(wù)地址(uri:地址绊序,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言硕舆,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱骤公,用來(lái)標(biāo)識(shí)不同環(huán)境的配置抚官。由 spring.profiles.active 的值來(lái)決定使用哪組配置。
## 熔斷
profiles: route_hystrix
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合阶捆,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由凌节,它由唯一標(biāo)識(shí)(ID)、目標(biāo)服務(wù)地址(uri)洒试、一組斷言(predicates)和一組過(guò)濾器組成(filters)倍奢。filters 不是必需參數(shù)。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)儡司,具有唯一性) 熔斷
- id: route_hystrix
# 目標(biāo)服務(wù)地址(uri:地址娱挨,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器捕犬,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
## 熔斷
- name: Hystrix
args:
name: fallbackcmd
### fallback 時(shí)調(diào)用的方法 http://localhost:8000/fallback
fallbackUri: forward:/fallback
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱跷坝,用來(lái)標(biāo)識(shí)不同環(huán)境的配置。由 spring.profiles.active 的值來(lái)決定使用哪組配置碉碉。
## 限流
profiles: route_requestRateLimiter
redis:
host: localhost
port: 6379
database: 0
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合柴钻,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由,它由唯一標(biāo)識(shí)(ID)垢粮、目標(biāo)服務(wù)地址(uri)贴届、一組斷言(predicates)和一組過(guò)濾器組成(filters)。filters 不是必需參數(shù)蜡吧。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)毫蚓,具有唯一性) 限流
- id: route_requestRateLimiter
# 目標(biāo)服務(wù)地址(uri:地址,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言昔善,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器元潘,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
## 限流
- name: RequestRateLimiter
args:
### 限流過(guò)濾器的 Bean 名稱
key-resolver: '#{@uriKeyResolver}'
### 希望允許用戶每秒處理多少個(gè)請(qǐng)求
redis-rate-limiter.replenishRate: 1
### 用戶允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
redis-rate-limiter.burstCapacity: 3
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
---
spring:
# 配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置君仆。由 spring.profiles.active 的值來(lái)決定使用哪組配置翩概。
## 綜合
profiles: route_all
redis:
host: localhost
port: 6379
database: 0
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由返咱,它由唯一標(biāo)識(shí)(ID)钥庇、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)咖摹。filters 不是必需參數(shù)评姨。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 綜合
- id: route_all
# 目標(biāo)服務(wù)地址(uri:地址楞艾,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言参咙,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/routeAll龄广,/all 部分會(huì)被下面的過(guò)濾器給截取掉
- Path=/all/routeAll
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器硫眯,過(guò)濾規(guī)則)
filters:
## 截取路徑位數(shù)
- StripPrefix=1
## 添加指定參數(shù)
- AddRequestParameter=pass, yes
## 熔斷
- name: Hystrix
args:
name: fallbackcmd
### fallback 時(shí)調(diào)用的方法 http://localhost:8000/fallback
fallbackUri: forward:/fallback
## 限流
- name: RequestRateLimiter
args:
### 限流過(guò)濾器的 Bean 名稱
key-resolver: '#{@uriKeyResolver}'
### 希望允許用戶每秒處理多少個(gè)請(qǐng)求
redis-rate-limiter.replenishRate: 1
### 用戶允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
redis-rate-limiter.burstCapacity: 3
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
注意配置注冊(cè)中心地址的端口都為 8761 也就是上面注冊(cè)中心工程配置的端口
每一對(duì) '---' 符號(hào)中的配置文件都是單獨(dú)的蕴侧,使用 spring.profiles.active 指定
每一對(duì) '---' 符號(hào)中的配置文件都只配置了一個(gè) route(路由)
route(路由)由四部分組成,其中 filters 不是必須參數(shù)
唯一標(biāo)識(shí)(ID)两入、目標(biāo)服務(wù)地址(uri)净宵、一組斷言(predicates)和一組過(guò)濾器組成(filters)
master-service - 簡(jiǎn)單嘗試
spring:
# 配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置裹纳。由 spring.profiles.active 的值來(lái)決定使用哪組配置择葡。
## 簡(jiǎn)單嘗試
profiles: route_simple
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由剃氧,它由唯一標(biāo)識(shí)(ID)敏储、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)朋鞍。filters 不是必需參數(shù)已添。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 簡(jiǎn)單嘗試
- id: route_simple
# 目標(biāo)服務(wù)地址(uri:地址滥酥,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: https://www.zouwencong.com
# 路由條件(predicates:斷言更舞,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/archive
- Path=/archive
停止注冊(cè)中心工程(registry-service)、服務(wù)工程 A 和服務(wù)工程 B
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_simple
-
上面配置文件內(nèi)容意思是當(dāng)訪問(wèn) http://localhost:8000/archive (網(wǎng)關(guān)地址/archive)
會(huì)被轉(zhuǎn)發(fā)到 https://www.zouwencong.com/archive/ (uri/archive)
啟動(dòng)注冊(cè)中心工程(registry-service)和網(wǎng)關(guān)工程(master-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/archive
發(fā)現(xiàn)頁(yè)面會(huì)自動(dòng)被跳轉(zhuǎn)到:https://www.zouwencong.com/archive/
證明服務(wù)轉(zhuǎn)發(fā)成功
master-service - 截取請(qǐng)求
spring:
#配置文件名稱坎吻,用來(lái)標(biāo)識(shí)不同環(huán)境的配置缆蝉。由 spring.profiles.active 的值來(lái)決定使用哪組配置。
##截取請(qǐng)求
profiles: route_stripPrefix
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合瘦真,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由刊头,它由唯一標(biāo)識(shí)(ID)、目標(biāo)服務(wù)地址(uri)诸尽、一組斷言(predicates)和一組過(guò)濾器組成(filters)原杂。filters 不是必需參數(shù)。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)弦讽,具有唯一性) 截取請(qǐng)求
- id: route_simple
# 目標(biāo)服務(wù)地址(uri:地址污尉,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: https://www.zouwencong.com
# 路由條件(predicates:斷言,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/archive往产,/str 部分會(huì)被下面的過(guò)濾器給截取掉
- Path=/str/archive
filters:
## 截取路徑位數(shù)
- StripPrefix=1
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)和網(wǎng)關(guān)工程(master-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_stripPrefix
-
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/str/archive (網(wǎng)關(guān)地址/str/archive)截取 /str 部分被碗,
截取后被轉(zhuǎn)發(fā)到 https://www.zouwencong.com/archive/ (uri/archive)
啟動(dòng)注冊(cè)中心工程(registry-service)和網(wǎng)關(guān)工程(master-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/str/archive
發(fā)現(xiàn)頁(yè)面會(huì)自動(dòng)被跳轉(zhuǎn)到:https://www.zouwencong.com/archive/
證明路徑被截取并服務(wù)轉(zhuǎn)發(fā)成功
master-service - 轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
spring:
#配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置仿村。由 spring.profiles.active 的值來(lái)決定使用哪組配置锐朴。
##轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
profiles: route_uri
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由蔼囊,它由唯一標(biāo)識(shí)(ID)焚志、目標(biāo)服務(wù)地址(uri)衣迷、一組斷言(predicates)和一組過(guò)濾器組成(filters)。filters 不是必需參數(shù)酱酬。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)壶谒,具有唯一性) 轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)
- id: route_uri
# 目標(biāo)服務(wù)地址(uri:地址,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: http://localhost:9000
# 路由條件(predicates:斷言膳沽,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器汗菜,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=name, zwc
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)和網(wǎng)關(guān)工程(master-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_uri
-
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/name (網(wǎng)關(guān)地址/name)
會(huì)被轉(zhuǎn)發(fā)到 http://localhost:9000/name(uri/name),并傳入 'name=zwc' 參數(shù)(注意為 Get 請(qǐng)求)
啟動(dòng)注冊(cè)中心工程(registry-service),網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A(a-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/name
輸出內(nèi)容:'My name is zwc. aaa'(通過(guò)網(wǎng)關(guān)轉(zhuǎn)發(fā) - 參數(shù)有值)
打開(kāi)新頁(yè)面訪問(wèn):http://localhost:9000/name
輸出內(nèi)容:'My name is null. aaa'(直接訪問(wèn) - 參數(shù)沒(méi)有值)
證明轉(zhuǎn)發(fā)指定地址并傳入?yún)?shù)成功
master-service - 轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
spring:
#配置文件名稱挑社,用來(lái)標(biāo)識(shí)不同環(huán)境的配置陨界。由 spring.profiles.active 的值來(lái)決定使用哪組配置。
##轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
profiles: route_addRequestParameter
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合痛阻,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由菌瘪,它由唯一標(biāo)識(shí)(ID)、目標(biāo)服務(wù)地址(uri)阱当、一組斷言(predicates)和一組過(guò)濾器組成(filters)俏扩。filters 不是必需參數(shù)。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí)斗这,具有唯一性) 轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)
- id: route_addRequestParameter
# 目標(biāo)服務(wù)地址(uri:地址动猬,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器表箭,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)赁咙,網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A(a-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_addRequestParameter
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/age (網(wǎng)關(guān)地址/age)會(huì)被轉(zhuǎn)發(fā)到 http://gateway-service/age(uri/age),并傳入 'age=three' 參數(shù)(注意為 Get 請(qǐng)求)
注意此處的配置 uri: lb://gateway-service 與之前都有所不同免钻,之前都是指定了明確的轉(zhuǎn)發(fā)地址彼水,可以滿足單個(gè)服務(wù)轉(zhuǎn)發(fā)的需求,但是一般情況都會(huì)有多個(gè)服務(wù)极舔,所以這里是指定的服務(wù)名稱凤覆,格式為:lb://應(yīng)用注冊(cè)服務(wù)名。
啟動(dòng)注冊(cè)中心工程(registry-service),網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service拆魏、b-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/age
這時(shí)可能會(huì)報(bào)錯(cuò) 500.錯(cuò)誤信息為 'Unable to find instance for gateway-service'
這種情況不要慌張盯桦,只是服務(wù)還沒(méi)有被注冊(cè)到注冊(cè)中心,稍等片刻再訪問(wèn)
多次訪問(wèn):http://localhost:8000/age
輪流輸出內(nèi)容:'I am three years old this year. aaa' 和 'I am three years old this year. bbb'
此時(shí)還通過(guò)網(wǎng)關(guān)達(dá)到了負(fù)載均衡的效果
證明轉(zhuǎn)發(fā)指定服務(wù)并傳入?yún)?shù)成功
master-service - 熔斷
spring:
#配置文件名稱渤刃,用來(lái)標(biāo)識(shí)不同環(huán)境的配置拥峦。由 spring.profiles.active 的值來(lái)決定使用哪組配置。
##熔斷
profiles: route_hystrix
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合卖子,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由略号,它由唯一標(biāo)識(shí)(ID)、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)玄柠。filters 不是必需參數(shù)突梦。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 熔斷
- id: route_hystrix
# 目標(biāo)服務(wù)地址(uri:地址羽利,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言宫患,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
## 熔斷
- name: Hystrix
args:
name: fallbackcmd
### fallback 時(shí)調(diào)用的方法 http://localhost:8000/fallback
fallbackUri: forward:/fallback
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)铐伴,網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service撮奏、b-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_hystrix
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/age (網(wǎng)關(guān)地址/age)會(huì)被轉(zhuǎn)發(fā)到 http://gateway-service/age(uri/age)俏讹,并傳入 'age=three' 參數(shù)(注意為 Get 請(qǐng)求)
注意此處的配置 uri: lb://gateway-service 與之前都有所不同当宴,之前都是指定了明確的轉(zhuǎn)發(fā)地址,可以滿足單個(gè)服務(wù)轉(zhuǎn)發(fā)的需求泽疆,但是一般情況都會(huì)有多個(gè)服務(wù)户矢,所以這里是指定的服務(wù)名稱,格式為:lb://應(yīng)用注冊(cè)服務(wù)名殉疼。
此處還多配置了一個(gè)過(guò)濾器 '- name: Hystrix'(熔斷)
當(dāng)請(qǐng)求服務(wù)出錯(cuò)時(shí)梯浪,會(huì)調(diào)用 fallback,路徑為:http://localhost:8000/fallback (網(wǎng)關(guān)地址/fallback)
此時(shí)就需要如下前端控制器
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 網(wǎng)關(guān)斷路器
* @Date 2019/6/23 19:33
* @Version 1.0
*/
@RestController
public class FallbackController {
/*
* @ClassName FallbackController
* @Desc TODO 網(wǎng)關(guān)斷路器
* @Date 2019/6/23 19:35
* @Version 1.0
*/
@RequestMapping("/fallback")
public String fallback() {
return "I'm Spring Cloud Gateway fallback.";
}
}
啟動(dòng)注冊(cè)中心工程(registry-service),網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service瓢娜、b-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/age
輸出內(nèi)容:'I'm Spring Cloud Gateway fallback.'
證明熔斷成功
master-service - 限流(重點(diǎn)挂洛,解決不生效問(wèn)題)
spring:
#配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置眠砾。由 spring.profiles.active 的值來(lái)決定使用哪組配置虏劲。
##限流
profiles: route_requestRateLimiter
redis:
host: localhost
port: 6379
database: 0
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由褒颈,它由唯一標(biāo)識(shí)(ID)柒巫、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)谷丸。filters 不是必需參數(shù)堡掏。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 限流
- id: route_requestRateLimiter
# 目標(biāo)服務(wù)地址(uri:地址刨疼,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言泉唁,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器,過(guò)濾規(guī)則)
filters:
## 添加指定參數(shù)
- AddRequestParameter=age, three
## 限流
- name: RequestRateLimiter
args:
### 限流過(guò)濾器的 Bean 名稱
key-resolver: '#{@uriKeyResolver}'
### 希望允許用戶每秒處理多少個(gè)請(qǐng)求
redis-rate-limiter.replenishRate: 1
### 用戶允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
redis-rate-limiter.burstCapacity: 3
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)揩慕,網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service亭畜、b-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改route_requestRateLimiter
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/age (網(wǎng)關(guān)地址/age)會(huì)被轉(zhuǎn)發(fā)到 http://gateway-service/age(uri/age),并傳入 'age=three' 參數(shù)(注意為 Get 請(qǐng)求)
注意此處還需要配置 redis 的連接信息
注意此處是結(jié)合 redis 實(shí)現(xiàn)的限流漩绵,所以 filter 過(guò)濾器的 name 必須為 RequestRateLimiter
并且通過(guò)實(shí)現(xiàn) KeyResolver 類來(lái)自定義限流策略贱案,如下
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 網(wǎng)關(guān)限流過(guò)濾器
* @Date 2019/6/23 17:59
* @Version 1.0
*/
public class UriKeyResolver implements KeyResolver {
/*
* @ClassName UriKeyResolver
* @Desc TODO 根據(jù)請(qǐng)求的 uri 限流
* @Date 2019/6/29 17:25
* @Version 1.0
*/
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return Mono.just(exchange.getRequest().getURI().getPath());
}
}
啟動(dòng)本地 redis(redis-server.exe) 服務(wù)
啟動(dòng)注冊(cè)中心工程(registry-service),網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service、b-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/age
此時(shí)限流卻無(wú)論如何都不生效,原因有如下兩點(diǎn)
① redis-server 版本過(guò)低宝踪!我 Windows 本地是 redis-2.4.2 版本的侨糟,要用 3 以上的版本!4裨铩秕重!
② 數(shù)據(jù)在 redis 中存儲(chǔ)的時(shí)間只有幾秒,所以得使用 monitor 指令來(lái)動(dòng)態(tài)的觀察@靼颉H茉拧!
打開(kāi) redis-cli.exe服鹅,輸入命令 monitor
快速刷新地址:http://localhost:8000/age
頁(yè)面上會(huì)出現(xiàn) 429凳兵,redis-cli.exe 中會(huì)出現(xiàn)很多數(shù)據(jù)交互(request_rate_limiter.xxx 開(kāi)頭的 key)
證明限流成功
master-service - 綜合
spring:
#配置文件名稱,用來(lái)標(biāo)識(shí)不同環(huán)境的配置企软。由 spring.profiles.active 的值來(lái)決定使用哪組配置庐扫。
##綜合
profiles: route_all
redis:
host: localhost
port: 6379
database: 0
application:
# 應(yīng)用名稱
name: gateway-master
cloud:
gateway:
discovery:
locator:
# 是否和服務(wù)注冊(cè)與發(fā)現(xiàn)組件結(jié)合,設(shè)置為 true 后可以直接使用應(yīng)用名稱調(diào)用服務(wù)
enabled: true
# 路由(routes:路由仗哨,它由唯一標(biāo)識(shí)(ID)形庭、目標(biāo)服務(wù)地址(uri)、一組斷言(predicates)和一組過(guò)濾器組成(filters)厌漂。filters 不是必需參數(shù)萨醒。)
routes:
# 路由標(biāo)識(shí)(id:標(biāo)識(shí),具有唯一性) 綜合
- id: route_all
# 目標(biāo)服務(wù)地址(uri:地址苇倡,請(qǐng)求轉(zhuǎn)發(fā)后的地址)
uri: lb://gateway-service
# 路由條件(predicates:斷言富纸,匹配 HTTP 請(qǐng)求內(nèi)容)
predicates:
## 轉(zhuǎn)發(fā)地址格式為 uri/routeAll,/all 部分會(huì)被下面的過(guò)濾器給截取掉
- Path=/all/routeAll
## 匹配 GET 請(qǐng)求
- Method=GET
# 過(guò)濾器(filters:過(guò)濾器雏节,過(guò)濾規(guī)則)
filters:
## 截取路徑位數(shù)
- StripPrefix=1
## 添加指定參數(shù)
- AddRequestParameter=pass, yes
## 熔斷
- name: Hystrix
args:
name: fallbackcmd
### fallback 時(shí)調(diào)用的方法 http://localhost:8000/fallback
fallbackUri: forward:/fallback
## 限流
- name: RequestRateLimiter
args:
### 限流過(guò)濾器的 Bean 名稱
key-resolver: '#{@uriKeyResolver}'
### 希望允許用戶每秒處理多少個(gè)請(qǐng)求
redis-rate-limiter.replenishRate: 1
### 用戶允許在一秒鐘內(nèi)完成的最大請(qǐng)求數(shù)
redis-rate-limiter.burstCapacity: 3
eureka:
instance:
# 使用 ip 代替實(shí)例名
prefer-ip-address: true
# 實(shí)例的主機(jī)名
hostname: ${spring.cloud.client.ip-address}
# 實(shí)例的 ID 規(guī)則
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}
client:
serviceUrl:
# 注冊(cè)中心地址
defaultZone: http://${eureka.instance.hostname}:8761/eureka/
logging:
level:
# log 級(jí)別
org.springframework.cloud.gateway: debug
停止注冊(cè)中心工程(registry-service)胜嗓,網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service、b-service)
把 master-service - application.yml 配置文件中最上面的 spring.profiles.active 的值更改為 route_all
上面配置文件內(nèi)容意思是訪問(wèn)的路徑 http://localhost:8000/all/routeAll (網(wǎng)關(guān)地址/all/routeAll)截取 /all 部分钩乍,會(huì)被轉(zhuǎn)發(fā)到 http://gateway-service/routeAll(uri/routeAll)辞州,并傳入 'pass=yes' 參數(shù)(注意為 Get 請(qǐng)求)
啟動(dòng)注冊(cè)中心工程(registry-service),網(wǎng)關(guān)工程(master-service)和服務(wù)工程 A/B(a-service、b-service)
項(xiàng)目啟動(dòng)成功后訪問(wèn):http://localhost:8000/all/routeAll
首先會(huì)返回 'I'm Spring Cloud Gateway fallback.'寥粹,因?yàn)榉?wù)還未被注冊(cè)到注冊(cè)中心
然后會(huì)返回 '{"msg":"缺少憑證","code":-1}'变过,因?yàn)榕渲昧巳诌^(guò)濾器,如下
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 請(qǐng)求認(rèn)證過(guò)濾器
* @Date 2019/6/29 17:49
* @Version 1.0
*/
public class TokenFilter implements GlobalFilter{
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 請(qǐng)求對(duì)象
ServerHttpRequest request = exchange.getRequest();
// 響應(yīng)對(duì)象
ServerHttpResponse response = exchange.getResponse();
// 只有綜合路由才添加這個(gè)全局過(guò)濾器(routesId:route_all)
// 如果請(qǐng)求路徑中不存在 routeAll 字符串
if(request.getURI().toString().indexOf("routeAll") == -1){
System.out.println("filter -> return");
// 直接跳出
return chain.filter(exchange);
}
// 從請(qǐng)求中獲取 token 參數(shù)
String token = exchange.getRequest().getQueryParams().getFirst("token");
// 如果為空涝涤,那么將返回 401
if (token == null || token.isEmpty()) {
// 響應(yīng)消息內(nèi)容對(duì)象
JSONObject message = new JSONObject();
// 響應(yīng)狀態(tài)
message.put("code", -1);
// 響應(yīng)內(nèi)容
message.put("msg", "缺少憑證");
// 轉(zhuǎn)換響應(yīng)消息內(nèi)容對(duì)象為字節(jié)
byte[] bits = message.toJSONString().getBytes(StandardCharsets.UTF_8);
DataBuffer buffer = response.bufferFactory().wrap(bits);
// 設(shè)置響應(yīng)對(duì)象狀態(tài)碼 401
response.setStatusCode(HttpStatus.UNAUTHORIZED);
// 設(shè)置響應(yīng)對(duì)象內(nèi)容并且指定編碼媚狰,否則在瀏覽器中會(huì)中文亂碼
response.getHeaders().add("Content-Type", "text/plain;charset=UTF-8");
// 返回響應(yīng)對(duì)象
return response.writeWith(Mono.just(buffer));
}
// 獲取請(qǐng)求地址
String beforePath = request.getPath().pathWithinApplication().value();
// 獲取響應(yīng)狀態(tài)碼
HttpStatus beforeStatusCode = response.getStatusCode();
System.out.println("響應(yīng)碼:" + beforeStatusCode + ",請(qǐng)求路徑:" + beforePath);
// 請(qǐng)求前
System.out.println("filter -> before");
// 如果不為空阔拳,就通過(guò)
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
// 獲取請(qǐng)求地址
String afterPath = request.getPath().pathWithinApplication().value();
// 獲取響應(yīng)狀態(tài)碼
HttpStatus afterStatusCode = response.getStatusCode();
System.out.println("響應(yīng)碼:" + afterStatusCode + "崭孤,請(qǐng)求路徑:" + afterPath);
// 響應(yīng)后
System.out.println("filter -> after");
}));
}
}
全局過(guò)濾器,不需要配置在配置文件中,作用于所有路由辨宠;只是這里在處理前做了判斷遗锣,只有路徑中存在routeAll 字符串才到后續(xù)處理;并且處理分為請(qǐng)求前的處理嗤形,和響應(yīng)后的處理
此時(shí)在地址:http://localhost:8000/all/routeAll 中添加 token 參數(shù)
輪流輸出內(nèi)容:'Can I pass? yes! port:9000' 和 'Can I pass? yes! port:9001'
觀察 gateway 工程的控制臺(tái)精偿,會(huì)有如下內(nèi)容輸出
響應(yīng)碼:null,請(qǐng)求路徑:/routeAll
filter -> before
響應(yīng)碼:200赋兵,請(qǐng)求路徑:/routeAll
filter -> after
13. 證明全局過(guò)濾器過(guò)濾成功
service 工程 - 項(xiàng)目結(jié)構(gòu)
把多工程項(xiàng)目使用 IntelliJ IDEA 打開(kāi)
1.把項(xiàng)目從 GitHub 中下載到你的本地
2.打開(kāi) IntelliJ IDEA
3.點(diǎn)擊 File -> Open
4.打開(kāi)你下載到本地的項(xiàng)目目錄
5.springcloud-gateway -> springcloud-gateway-service(選擇打開(kāi)此工程)
6.打開(kāi) service 工程后
7.再次點(diǎn)擊 File -> Project Structrue
8.選擇 Modules笔咽,點(diǎn)擊 '+' 符號(hào)
9.點(diǎn)擊 Import Module
10.還是打開(kāi)你下載到本地的項(xiàng)目目錄
11.springcloud-gateway -> springcloud-gateway-commons -> pom.xml
12.點(diǎn)擊 OK
13.點(diǎn)擊 Next,F(xiàn)inish
14.點(diǎn)擊 Apply霹期,OK