微服務(wù)架構(gòu)
- SpringCloud
服務(wù)注冊發(fā)現(xiàn):Nacos
服務(wù)限流降級:Sentinel
分布配置中?:Nacos
分布式事務(wù)保證數(shù)據(jù)一致性:Seata
分布式定時任務(wù):Spring Scheduling Tasks
服務(wù)?關(guān):SpringCloud Gateway
異步消息削峰填谷:RocketMQ
服務(wù)之間調(diào)?:OpenFeign、Ribbon
鏈路追蹤:Sleuth+Zipkin
技術(shù)棧版本控制
| 序號 | 名稱 | 版本 | 用途 | 備注 |
|---|---|---|---|---|
| 1 | openJDK | 21 | Java JDK | |
| 2 | postgresSQL | 17.4 | 基礎(chǔ)數(shù)據(jù)庫 | |
| 3 | Maven | 3.9.9 | Java第三方依賴包管理工具 | |
| 4 | springboot | 3.4.3 | Java MVC框架 | |
| 5 | springcloud | 2024.0.1 | 微服務(wù)框架 | |
| 6 | springcloud Alibaba | 2023.0.3.2 | 阿里巴巴微服務(wù)框架擴(kuò)展 |
組件版本控制
| 序號 | 名稱 | 版本 | 用途 | 備注 |
|---|---|---|---|---|
| 1 | Nacos | 2.5.1 | 服務(wù)注冊發(fā)現(xiàn)、分布配置中? | |
| 2 | Sentinel | 1.8.8 | 服務(wù)限流降級 | 面向云原生微服務(wù)的高可用流控防護(hù)組件 |
| 3 | Seata | 2.3.0 | 分布式事務(wù)保證數(shù)據(jù)一致性 |
什么是?關(guān)
- API Gateway,是系統(tǒng)的唯?對外的??,介于客戶端和服務(wù)器端之間的中間層,處理?業(yè)務(wù)功能 提供路由請求、鑒權(quán)、監(jiān)控、緩存、限流等功能
- 統(tǒng)?接?
智能路由
AB測試、灰度測試
負(fù)載均衡、容災(zāi)處理
?志埋點(類似Nignx?志)- 流量監(jiān)控
限流處理
服務(wù)降級- 安全防護(hù)
鑒權(quán)處理
監(jiān)控
機(jī)器?絡(luò)隔離
主流的?關(guān)
- zuul:是Netflix開源的微服務(wù)?關(guān),和
Eureka,Ribbon,Hystrix等組件配合使?,依賴組件?
較多,性能教差- kong: 由Mashape公司開源的,基于Nginx的API
gateway- nginx+lua:是?個?性能的HTTP和反向代理服務(wù)器,lua
是腳本語?,讓Nginx執(zhí)?Lua腳本,并且?并發(fā)、?阻塞
的處理各種請求- springcloud gateway: Spring公司專?開發(fā)的?關(guān),替代
zuul
注意:AlibabaCloud對應(yīng)的?關(guān),?
SpringCloud官?推薦的Gateway
什么是 SpringCloud Gateway
Spring官?出品,基于Spring5+Reactor技術(shù)開發(fā)的?關(guān)
性能強(qiáng)勁基于Reactor+WebFlux、功能多樣基于springboot2.x, 直接可以jar包?式運(yùn)?
官??檔
https://spring.io/projects/spring-cloud-gateway
項目使用
注:這里僅helloworld一下,下一小章節(jié)會按實際使用結(jié)合nginx使用。
新建微服務(wù)online-edu-gateway


建好之后刪掉Main.java

配置online-edu-api-gateway/pom.xml,增加網(wǎng)關(guān)依賴。
<?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>org.online_edu</groupId>
<artifactId>online-edu</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>online-edu-api-gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
新增并配置online-edu-api-gateway/src/main/java/org/online_edu/GatewayApplication.java
package org.online_edu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication()
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
新增并配置online-edu-api-gateway/src/main/resources/application.yml.
server:
port: 8888
spring:
application:
name: online-edu-api-gateway
cloud:
gateway:
routes: #數(shù)組形式
- id: order-service #路由唯?標(biāo)識
uri: http://127.0.0.1:8000 #想要轉(zhuǎn)發(fā)到的地址
order: 1 #優(yōu)先級,數(shù)字越?優(yōu)先級越?
predicates: #斷? 配置哪個路徑才轉(zhuǎn)發(fā)
- Path=/order-server/**
filters: #過濾器,請求在傳遞過程中通過過濾器修改
- StripPrefix=1 #去掉第?層前綴
#訪問路徑 http://localhost:8888/order-server/api/v1/video_order/list
#轉(zhuǎn)發(fā)路徑 http://localhost:8000/order-server/api/v1/video_order/list
#需要過濾器去掉前?第?層
啟動網(wǎng)關(guān)服務(wù)online-edu-api-gateway和訂單服務(wù)online-edu-order-service.
瀏覽器打開http://localhost:8888/order-server/api/v1/video_order/list

gateway整合nacos
- 原先存在的問題
微服務(wù)地址寫死
負(fù)載均衡沒做到
實際使用中,我們不可能將微服務(wù)的地址和ip寫死,而是通過nacos作為注冊中心,進(jìn)行自動的服務(wù)發(fā)現(xiàn)。
配置online-edu-api-gateway/pom.xml,增加naocs依賴。
<?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>org.online_edu</groupId>
<artifactId>online-edu</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>online-edu-api-gateway</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--添加nacos客戶端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- Spring Cloud 2020 版本后默認(rèn)移除了 Ribbon,需手動添加 spring-cloud-loadbalancer 依賴以實現(xiàn) lb:// 負(fù)載均衡路由。-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>
</dependencies>
</project>
配置online-edu-api-gateway/src/main/resources/application.yml,增加nacos配置。
server:
port: 8888
spring:
application:
name: online-edu-api-gateway
cloud:
nacos:
discovery:
server-addr: xxx.xxx.xxx.xxx:8848
username: nacos
password: password
gateway:
routes: #數(shù)組形式
- id: order-service #路由唯?標(biāo)識
# uri: http://127.0.0.1:8000 #想要轉(zhuǎn)發(fā)到的地址
uri: lb://online-edu-order-service # 從nacos獲取名稱轉(zhuǎn)發(fā),lb是負(fù)載均衡輪訓(xùn)策略
order: 1 #優(yōu)先級,數(shù)字越?優(yōu)先級越?
predicates: #斷? 配置哪個路徑才轉(zhuǎn)發(fā)
- Path=/order-server/**
filters: #過濾器,請求在傳遞過程中通過過濾器修改
- StripPrefix=1 #去掉第?層前綴
#訪問路徑 http://localhost:8888/order-server/api/v1/video_order/list
#轉(zhuǎn)發(fā)路徑 http://localhost:8000/order-server/api/v1/video_order/list
#需要過濾器去掉前?第?層
discovery:
locator:
enabled: true #開啟?關(guān)拉取nacos的服務(wù)
訂單服務(wù)online-edu-order-service開啟多實例啟動。


修改端口再啟動一個:

瀏覽器打開
http://localhost:8888/order-server/api/v1/video_order/list
再次刷新

Gateway?關(guān)的配置項
以下僅作為網(wǎng)關(guān)功能演示。實際使用網(wǎng)關(guān)過程中,注意:
?關(guān)不要加太多業(yè)務(wù)邏輯,否則會影響性能,務(wù)必記住

路由:是?關(guān)的基本單元,由ID、URI、?組
Predicate、?組Filter組成,根據(jù)Predicate進(jìn)?匹配轉(zhuǎn)發(fā)
route組成部分
id:路由的ID
uri:匹配路由的轉(zhuǎn)發(fā)地址
predicates:配置該路由的斷?,通過PredicateDefinition類進(jìn)?接收配置。
order:路由的優(yōu)先級,數(shù)字越?,優(yōu)先級越?
交互流程
- 客戶端向Spring Cloud Gateway發(fā)出請求
- 如果?關(guān)處理程序映射確定請求與路由匹配
- 則將其發(fā)送到?關(guān)Web處理程序
- 通過特定過濾器鏈運(yùn)?,前置處理-后置處理

Gateway內(nèi)置的路由斷?
什么是Gateway路由斷?
- Predicate 來源于Java8,接受輸?參數(shù),返回?個布爾值結(jié)果
- Spring Cloud Gateway 中 Spring 利? Predicate 的特性實現(xiàn)了各種路由匹配規(guī)則
- 轉(zhuǎn)發(fā)的判斷條件,SpringCloud Gateway?持多種?式,常?如:Path、Query、Method、Header等
- ?持多個Predicate請求的轉(zhuǎn)發(fā)是必須滿?所有的Predicate后才可以進(jìn)?路由轉(zhuǎn)發(fā)
內(nèi)置路由斷?—— RoutePredicateFactory 接?實現(xiàn)類
進(jìn)入idea項目中,ctrl+N,搜索RoutePredicateFactory 類。

按住ctrl+Alt,點擊接?實現(xiàn)類RoutePredicateFactory 名稱,可以查詢到下游的實現(xiàn)類:

參數(shù)編寫規(guī)則 XXXRoutePredicateFactory,使?XXX作為
參數(shù)配置, 例如下?
predicates:
- Host=
- Path=
- Method=
- Header=
- Query=
- Cookie=
斷言使用舉例
比如,某個接口,要求在指定時間定時下線。過后不可以在被訪問。
使?Before ,只要當(dāng)前時間?于設(shè)定時間,路由才會匹配請求
東8區(qū)的2025-03-28T01:01:01.000+08:00后,請求不可訪問
配置online-edu-api-gateway/src/main/resources/application.yml
server:
port: 8888
spring:
application:
name: online-edu-api-gateway
cloud:
nacos:
discovery:
server-addr: xxx.xxx.xxx.xxx:8848
username: nacos
password: password
gateway:
routes: #數(shù)組形式
- id: order-service #路由唯?標(biāo)識
# uri: http://127.0.0.1:8000 #想要轉(zhuǎn)發(fā)到的地址
uri: lb://online-edu-order-service # 從nacos獲取名稱轉(zhuǎn)發(fā),lb是負(fù)載均衡輪訓(xùn)策略
order: 1 #優(yōu)先級,數(shù)字越?優(yōu)先級越?
predicates: #斷? 配置哪個路徑才轉(zhuǎn)發(fā)
- Path=/order-server/**
- Before=2025-03-28T01:01:01.000+08:00
# - RewritePath=/order-server/(?<remaining>.*), /$\{remaining}
filters: #過濾器,請求在傳遞過程中通過過濾器修改
- StripPrefix=1 #去掉第?層前綴
discovery:
locator:
enabled: true #開啟網(wǎng)關(guān)拉取nacos的服務(wù)
重新運(yùn)行網(wǎng)關(guān)服務(wù),瀏覽器運(yùn)行,沒問題(運(yùn)行時,當(dāng)前北京時間2025年3月27日)

改為Before=2025-03-26T01:01:01.000+08:00
瀏覽器運(yùn)行:

例如增加必須傳的參數(shù)
predicates: #斷? 配置哪個路徑才轉(zhuǎn)發(fā)
- Path=/order-server/**
- Before=2025-03-28T01:01:01.000+08:00
- Query=token
瀏覽器運(yùn)行:


Gateway?關(guān)的過濾器
過濾器?命周期
- PRE: 這種過濾器在請求被路由之前調(diào)?,?般?于鑒權(quán)、限流等
- POST:這種過濾器在路由到微服務(wù)以后執(zhí)?,?般?于修改響應(yīng)結(jié)果,?如增加header信息、打點結(jié)果?志
?關(guān)過濾器分類
- 局部過濾器GatewayFilter:應(yīng)?在某個路由上,每個過濾器??都對應(yīng)?個實現(xiàn)類,并且這些類的名稱必須以GatewayFilterFactory 結(jié)尾.內(nèi)置很多全局過濾器,頂級接? GlobalFilter
- 全局過濾器:作?全部路由上,內(nèi)置很多局部過濾器,頂級接? GatewayFilterFactory
?定義全局過濾器實現(xiàn)鑒權(quán)
自定義實現(xiàn),本質(zhì)上就是模仿官方的過濾器,寫一個自己的java類。
新建online-edu-api-gateway/src/main/java/org/online_edu/filter/UserGlobalFilter.java
package org.online_edu.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class UserGlobalFilter implements GlobalFilter, Ordered {
/**
* 處理Web請求并(可選地)委托給下一個{@code GatewayFilter}
* 通過給定的{@link GatewayFilterChain}。
*
* @param chain 鏈提供了一種委托給下一個過濾器的方式
* @param exchange 交換當(dāng)前服務(wù)器交換
* @return {@code Mono<Void>} 表示請求處理完成
*/
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 寫業(yè)務(wù)邏輯
return null;
}
/**
* 獲取該對象的順序值。
* 值越高優(yōu)先級越低。因此,
* 具有最低值的對象具有最高優(yōu)先級(在某種程度上)
* 類似于Servlet {@code load-on-startup}值)。
* 相同的順序值將導(dǎo)致任意的排序位置受影響的對象。
*
* @return 返回排序闕值
* @see #HIGHEST_PRECEDENCE
* @see #LOWEST_PRECEDENCE
*/
@Override
public int getOrder() {
return 0;
}
}
模擬寫登錄鑒權(quán)邏輯,這里引入一個工具包apache-commons-lang3。
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
如果拉不下來就手動下載一下。
DremoteRepositories=https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -DgroupId=org.apache.commons -DartifactId=commons-lang3 -Dversion=3.17.0

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 寫業(yè)務(wù)邏輯
String token = exchange.getRequest().getHeaders().getFirst("token");
//TODO 根據(jù)業(yè)務(wù)開發(fā)對應(yīng)的鑒權(quán)規(guī)則,比如JWT
if (StringUtils.isBlank(token)) {
// 返回401
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
//繼續(xù)往下執(zhí)?
return chain.filter(exchange);
}
online-edu-api-gateway/src/main/resources/application.yml記得注釋掉多余的斷言。
server:
port: 8888
spring:
application:
name: online-edu-api-gateway
cloud:
nacos:
discovery:
server-addr: xxx.xxx.xxx.xxx:8848
username: nacos
password: password
gateway:
routes: #數(shù)組形式
- id: order-service #路由唯?標(biāo)識
# uri: http://127.0.0.1:8000 #想要轉(zhuǎn)發(fā)到的地址
uri: lb://online-edu-order-service # 從nacos獲取名稱轉(zhuǎn)發(fā),lb是負(fù)載均衡輪訓(xùn)策略
order: 1 #優(yōu)先級,數(shù)字越?優(yōu)先級越?
predicates: #斷? 配置哪個路徑才轉(zhuǎn)發(fā)
- Path=/order-server/**
# - Before=2025-03-28T01:01:01.000+08:00
# - Query=token
filters: #過濾器,請求在傳遞過程中通過過濾器修改
- StripPrefix=1 #去掉第?層前綴
discovery:
locator:
enabled: true #開啟網(wǎng)關(guān)拉取nacos的服務(wù)
運(yùn)行:

配置請求,并發(fā)送:
