SpringCloud Alibaba 核心組件解析:服務(wù)網(wǎng)關(guān)
技術(shù)棧:Spring Boot 3.2.0 + Spring Cloud Alibaba 2023.0.0.0-RC1 + Sentinel + Gateway + Nacos
6.1 是什么 — Sentinel 網(wǎng)關(guān)限流
Gateway 負(fù)責(zé)路由轉(zhuǎn)發(fā),Sentinel 負(fù)責(zé)流量控制。兩者整合后,可以在網(wǎng)關(guān)層對(duì)進(jìn)入微服務(wù)的流量進(jìn)行統(tǒng)一限流和熔斷,在請(qǐng)求到達(dá)微服務(wù)之前就攔截。
6.1.1 調(diào)用鏈路
客戶端請(qǐng)求
│
▼
┌─────────────────────────────┐
│ Gateway (9528) │
│ ┌─────────────────────────┐ │
│ │ SentinelGatewayFilter │ │ ← 在這里攔截!超閾值直接拒絕
│ │ (網(wǎng)關(guān)層限流 QPS=2) │ │
│ └─────────┬───────────────┘ │
│ │ 通過(guò)限流 │
└────────────┼────────────────┘
▼
┌─────────────────────────────┐
│ Provider (9001) │
│ ┌─────────────────────────┐ │
│ │ @SentinelResource │ │ ← 服務(wù)層精細(xì)化限流
│ └─────────────────────────┘ │
└─────────────────────────────┘6.1.2 網(wǎng)關(guān)限流 vs 服務(wù)限流
| 層級(jí) | 組件 | 粒度 | 場(chǎng)景 |
|---|---|---|---|
| 網(wǎng)關(guān)層 | GatewayFlowRule | 按路由或 API 分組 | 入口總流量控制 |
| 服務(wù)層 | @SentinelResource | 按接口/資源 | 精細(xì)化流量控制 |
6.2 為什么 — 網(wǎng)關(guān)層限流的優(yōu)勢(shì)
- 請(qǐng)求入口攔截:不讓無(wú)效請(qǐng)求進(jìn)入微服務(wù)層,節(jié)省資源
- 統(tǒng)一管理:所有路由規(guī)則集中在網(wǎng)關(guān)配置,不需要每個(gè)微服務(wù)各自配
- 安全防護(hù):惡意刷量在網(wǎng)關(guān)層就被攔截
6.3 怎么做 — 完整實(shí)戰(zhàn)
6.3.1 項(xiàng)目模塊
| 模塊 | 端口 | 說(shuō)明 |
|---|---|---|
clooudalibaba-sentinel-gateway9528 | 9528 | Sentinel + Gateway |
cloudalibaba-provider-payment9001 | 9001 | 被代理的服務(wù) |
6.3.2 步驟 ①:依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Sentinel 適配 Gateway 的橋接包 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>6.3.3 步驟 ②:配置
server:
port: 9528
spring:
application:
name: cloudalibaba-sentinel-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: pay_routh1
uri: http://localhost:9001 # 直接轉(zhuǎn)發(fā)到 Provider
predicates:
- Path=/pay/**
sentinel:
log:
dir: D:/yangnan/Documents/SpringCloud/sentinel-log6.3.4 步驟 ③:核心配置類
// clooudalibaba-sentinel-gateway9528/.../config/GatewayConfiguration.java
@Configuration
public class GatewayConfiguration {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(
ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
// ① 注冊(cè) Sentinel 異常處理器(最高優(yōu)先級(jí))
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(
viewResolvers, serverCodecConfigurer);
}
// ② 注冊(cè) Sentinel 全局過(guò)濾器(Order=-1,低于上方的處理器,但高于其他過(guò)濾器)
@Bean
@Order(-1)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
// ③ 應(yīng)用啟動(dòng)后初始化規(guī)則
@PostConstruct
public void doInit() {
initBlockHandler();
}
private void initBlockHandler() {
// 網(wǎng)關(guān)流控規(guī)則:對(duì)路由 pay_routh1 限制每秒最多 2 個(gè)請(qǐng)求
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("pay_routh1")
.setCount(2) // QPS 閾值
.setIntervalSec(1)); // 統(tǒng)計(jì)間隔 1 秒
GatewayRuleManager.loadRules(rules);
// 自定義限流響應(yīng)(返回 JSON 而不是默認(rèn) HTML)
BlockRequestHandler handler = (exchange, t) -> {
Map<String, String> map = new HashMap<>();
map.put("errorCode",
HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
map.put("errorMessage",
"請(qǐng)求太過(guò)頻繁,系統(tǒng)忙不過(guò)來(lái),觸發(fā)限流(sentinel+gateway整合Case)");
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(map));
};
GatewayCallbackManager.setBlockHandler(handler);
}
}配置解讀:
| 組件 | 作用 |
|---|---|
SentinelGatewayBlockExceptionHandler | 處理限流時(shí)拋出的 BlockException |
SentinelGatewayFilter | 攔截每個(gè)請(qǐng)求,執(zhí)行限流規(guī)則判斷 |
GatewayFlowRule | 網(wǎng)關(guān)級(jí)流控規(guī)則,按 routeId 限流 |
BlockRequestHandler | 自定義被限流時(shí)返回的錯(cuò)誤信息(JSON 格式) |
6.3.5 步驟 ④:驗(yàn)證
- 啟動(dòng) Nacos → Gateway(9528) → Provider(9001)
- 快速連續(xù)訪問(wèn)
http://localhost:9528/pay/nacos/1 - QPS > 2 時(shí)返回自定義 JSON:
{
"errorCode": "Too Many Requests",
"errorMessage": "請(qǐng)求太過(guò)頻繁,系統(tǒng)忙不過(guò)來(lái),觸發(fā)限流(sentinel+gateway整合Case)"
}6.4 深入原理 — 網(wǎng)關(guān)限流實(shí)現(xiàn)流程
請(qǐng)求到達(dá) Gateway
│
▼
SentinelGatewayFilter.doFilter()
│
├→ 提取 routeId(如 "pay_routh1")
├→ 匹配 GatewayFlowRule(QPS=2)
├→ 判斷是否超閾值
│
├→ 未超:chain.filter() → 轉(zhuǎn)發(fā)到 Provider ?
└→ 超了:throw BlockException → BlockRequestHandler → 返回 JSON ?6.5 網(wǎng)關(guān)限流 vs 服務(wù)限流對(duì)比
| 維度 | 網(wǎng)關(guān)限流 | 服務(wù)限流 |
|---|---|---|
| 實(shí)現(xiàn)方式 | GatewayFlowRule + SentinelGatewayFilter | @SentinelResource |
| 配置位置 | 網(wǎng)關(guān)代碼中硬編碼或動(dòng)態(tài)配置 | 控制臺(tái)或注解 |
| 粒度 | 按路由/API 分組 | 按資源名/URL |
| 優(yōu)勢(shì) | 統(tǒng)一入口,減少無(wú)效流量進(jìn)入 | 精細(xì)化控制 |
| 劣勢(shì) | 無(wú)法感知服務(wù)內(nèi)部邏輯 | 需要每個(gè)服務(wù)單獨(dú)配置 |
6.6 面試題
Q1:網(wǎng)關(guān)層限流和服務(wù)層限流如何選擇?
答:兩者不是替代關(guān)系而是互補(bǔ)關(guān)系。網(wǎng)關(guān)層做粗粒度總流量控制(如每秒不超過(guò) 1000),服務(wù)層做細(xì)粒度接口控制(如秒殺接口單獨(dú)限制)。雙層防護(hù)更安全。
Q2:Sentinel 網(wǎng)關(guān)限流和 Resilience4J RequestRateLimiter 有什么區(qū)別?
答:Sentinel 需要獨(dú)立部署 Dashboard,提供實(shí)時(shí)監(jiān)控和規(guī)則熱更新;Resilience4J RequestRateLimiter 是 Gateway 內(nèi)置過(guò)濾器,配置簡(jiǎn)單但功能有限。
6.7 踩坑指南
| 坑 | 現(xiàn)象 | 原因 | 解決 |
|---|---|---|---|
| ?? 過(guò)濾器優(yōu)先級(jí)不對(duì) | 限流不生效 | SentinelGatewayFilter 優(yōu)先級(jí)低于其他過(guò)濾器 | 確保 @Order(-1) |
| ?? 異常處理器不工作 | 限流后返回默認(rèn) HTML 錯(cuò)誤頁(yè) | SentinelGatewayBlockExceptionHandler 未注冊(cè)或優(yōu)先級(jí)不夠 | 確保 @Order(Ordered.HIGHEST_PRECEDENCE) |
| ?? sentinel-gateway-adapter 版本沖突 | NoClassDefFoundError | adapter 版本與 sentinel-core 不匹配 | 由 Spring Cloud Alibaba BOM 統(tǒng)一管理版本,不要手動(dòng)指定 |
6.8 章節(jié)總結(jié)
| 要點(diǎn) | 說(shuō)明 |
|---|---|
| 三個(gè)關(guān)鍵 Bean | SentinelGatewayFilter(攔截請(qǐng)求)+ SentinelGatewayBlockExceptionHandler(處理異常)+ GatewayFlowRule(配置規(guī)則) |
| 規(guī)則配置 | GatewayFlowRule("routeId").setCount(N).setIntervalSec(S) |
| 自定義響應(yīng) | BlockRequestHandler 返回 JSON,替代默認(rèn) HTML |
| 雙層防護(hù) | 網(wǎng)關(guān)層粗粒度 + 服務(wù)層細(xì)粒度,組合使用 |
| @Order 很重要 | HIGHEST_PRECEDENCE 給異常處理器,-1 給過(guò)濾器 |
到此這篇關(guān)于SpringCloud Alibaba 核心組件解析:服務(wù)網(wǎng)關(guān)的文章就介紹到這了,更多相關(guān)SpringCloud Alibaba 服務(wù)網(wǎng)關(guān)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringCloudAlibaba整合服務(wù)網(wǎng)關(guān)GateWay教程
- SpringCloud Alibaba Nacos服務(wù)注冊(cè)中心解讀
- SpringCloud alibaba使用Nacos配置中心解讀
- SpringCloudAlibaba極簡(jiǎn)入門(mén)整合Grpc代替OpenFeign的詳細(xì)過(guò)程
- Springcloud Alibaba超詳細(xì)使用詳解
- SpringCloud超詳細(xì)講解微服務(wù)網(wǎng)關(guān)Gateway
- SpringCloud超詳細(xì)講解微服務(wù)網(wǎng)關(guān)Zuul
相關(guān)文章
詳解SpringMVC中的@RequestMapping注解
這篇文章主要介紹了SpringMVC中@RequestMapping注解,@RequestMapping注解是一個(gè)用來(lái)處理請(qǐng)求地址映射的注解,可用于映射一個(gè)請(qǐng)求或一個(gè)方法,可以用在類或方法上,需要的朋友可以參考下2023-07-07
Java的super關(guān)鍵字與instanceof運(yùn)算符使用方法
這篇文章主要介紹了Java的super關(guān)鍵字與instanceof運(yùn)算符使用方法,是Java入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-09-09
guava中Multimap、HashMultimap用法小結(jié)
這篇文章主要介紹了guava中Multimap、HashMultimap使用,Multimap它可以很簡(jiǎn)單的實(shí)現(xiàn)一些功能,LinkedHashMultimap實(shí)現(xiàn)類與HashMultimap類的實(shí)現(xiàn)方法一樣,唯一的區(qū)別是LinkedHashMultimap保存了記錄的插入順序,本文就這些內(nèi)容講解的非常詳細(xì),需要的朋友參考下吧2022-05-05
Java 最優(yōu)二叉樹(shù)的哈夫曼算法的簡(jiǎn)單實(shí)現(xiàn)
這篇文章主要介紹了Java 最優(yōu)二叉樹(shù)的哈夫曼算法的簡(jiǎn)單實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
基于Freemarker和xml實(shí)現(xiàn)Java導(dǎo)出word
這篇文章主要介紹了基于Freemarker和xml實(shí)現(xiàn)Java導(dǎo)出word,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
Java工具類實(shí)現(xiàn)高效編寫(xiě)報(bào)表
對(duì)于報(bào)表數(shù)據(jù)大部分情況下使用寫(xiě)sql的方式為大屏/報(bào)表提供數(shù)據(jù)來(lái)源,但是對(duì)于某些復(fù)雜情況下僅僅使用sql無(wú)法實(shí)現(xiàn),這篇文章主要介紹了Java工具類實(shí)現(xiàn)高效編寫(xiě)報(bào)表2022-11-11
Java嵌套for循環(huán)的幾種常見(jiàn)優(yōu)化方案
這篇文章主要給大家介紹了關(guān)于Java嵌套for循環(huán)的幾種常見(jiàn)優(yōu)化,在Java中優(yōu)化嵌套for循環(huán)可以通過(guò)以下幾種方式來(lái)提高性能和效率,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
Java基于注解實(shí)現(xiàn)的鎖實(shí)例解析
這篇文章主要介紹了Java基于注解實(shí)現(xiàn)的鎖實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02

