Sentinel 實(shí)戰(zhàn):如何實(shí)現(xiàn)分布式系統(tǒng)的高效流量管控?
實(shí)現(xiàn)分布式系統(tǒng)的高效流量管控是微服務(wù)架構(gòu)中非常重要的一環(huán)。下面以 Spring Boot 和 Spring Cloud 框架為例,通過阿里巴巴的 Sentinel 組件實(shí)現(xiàn)多服務(wù)環(huán)境下的流量監(jiān)控與管控。我們將展示如何使用 Sentinel 配置流控規(guī)則、實(shí)現(xiàn)熔斷降級(jí)和跨服務(wù)流量管控,同時(shí)包含完整的代碼和配置。
系統(tǒng)設(shè)計(jì)目標(biāo)
- 模擬一個(gè)微服務(wù)架構(gòu):訂單服務(wù)(order-service)和庫存服務(wù)(inventory-service)。
- Sentinel 的核心功能:
- 在每個(gè)服務(wù)上設(shè)置流控規(guī)則,限制流量請(qǐng)求。
- 實(shí)現(xiàn)跨服務(wù)調(diào)用時(shí)的流量監(jiān)控。
- 配置熔斷降級(jí)規(guī)則,確保系統(tǒng)的穩(wěn)定性。
- 提供完整的整合代碼,包括服務(wù)配置、Sentinel 規(guī)則代碼和流量控制邏輯。
系統(tǒng)架構(gòu)圖
用戶請(qǐng)求 -> Gateway(網(wǎng)關(guān)) -> Order-Service -> Inventory-Service
流控目標(biāo):
- 限制 order-service 的并發(fā)訪問數(shù)為 10。
- 對(duì) inventory-service 的 QPS 設(shè)置為 5。
- 配置熔斷規(guī)則,若 inventory-service 超時(shí)率超過 50%,熔斷 10 秒。
- 在 Sentinel Dashboard 上實(shí)時(shí)監(jiān)控流量數(shù)據(jù)。
準(zhǔn)備工作
依賴引入
在所有服務(wù)中需要添加以下依賴。
pom.xml 公共依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Sentinel Dashboard 下載
下載并啟動(dòng) Sentinel 控制臺(tái)(建議使用最新版本):
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
核心服務(wù)實(shí)現(xiàn)
1、Order-Service(訂單服務(wù))
訂單服務(wù)負(fù)責(zé)接收用戶訂單請(qǐng)求,并調(diào)用庫存服務(wù)扣減庫存。
application.yml 配置
server:
port: 8081
spring:
application:
name: order-service
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 指定 Sentinel Dashboard 地址
port: 8719 # 服務(wù)與 Sentinel Dashboard 的通信端口
management:
endpoints:
web:
exposure:
include: '*'
主啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
控制層
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/create")
@SentinelResource(value = "createOrder", blockHandler = "handleOrderBlock")
public String createOrder(@RequestParam("productId") String productId) {
// 調(diào)用庫存服務(wù)扣減庫存
String result = restTemplate.getForObject("http://inventory-service/inventory/deduct?productId=" + productId, String.class);
return "Order created successfully! Result from inventory: " + result;
}
// 流控處理邏輯
public String handleOrderBlock(String productId, BlockException ex) {
return "Order service is busy. Please try again later.";
}
}
流控規(guī)則配置
@Configuration
public class SentinelConfig {
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
rule.setResource("createOrder"); // 資源名稱
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 基于 QPS 的流控
rule.setCount(10); // 最大 QPS 為 10
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
}
RestTemplate 配置
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2、Inventory-Service(庫存服務(wù))
庫存服務(wù)負(fù)責(zé)處理庫存扣減請(qǐng)求。
application.yml 配置
server:
port: 8082
spring:
application:
name: inventory-service
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8720
management:
endpoints:
web:
exposure:
include: '*'
主啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
public class InventoryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(InventoryServiceApplication.class, args);
}
}
控制層
@RestController
@RequestMapping("/inventory")
public class InventoryController {
@GetMapping("/deduct")
@SentinelResource(value = "deductInventory", blockHandler = "handleDeductBlock", fallback = "fallbackForDeduct")
public String deduct(@RequestParam("productId") String productId) {
// 模擬業(yè)務(wù)處理
if ("timeout".equals(productId)) {
try {
Thread.sleep(2000); // 模擬超時(shí)
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "Inventory deducted successfully for productId: " + productId;
}
// 流控處理邏輯
public String handleDeductBlock(String productId, BlockException ex) {
return "Inventory service is busy. Please try again later.";
}
// Fallback 邏輯
public String fallbackForDeduct(String productId, Throwable throwable) {
return "Fallback: Unable to process inventory deduction.";
}
}
熔斷規(guī)則配置
@Configuration
public class SentinelConfig {
@PostConstruct
public void initDegradeRules() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource("deductInventory");
rule.setGrade(RuleConstant.DEGRADE_GRADE_RT); // 基于響應(yīng)時(shí)間熔斷
rule.setCount(1000); // 超時(shí)閾值(ms)
rule.setTimeWindow(10); // 熔斷持續(xù)時(shí)間(秒)
rule.setMinRequestAmount(5); // 最小請(qǐng)求數(shù)
rule.setStatIntervalMs(60000); // 統(tǒng)計(jì)時(shí)間窗口(ms)
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
3、Gateway(網(wǎng)關(guān)服務(wù))
application.yml 配置
server:
port: 8080
spring:
application:
name: gateway
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8721
gateway:
routes:
- id: order-service
uri: http://localhost:8081
predicates:
- Path=/orders/**
- id: inventory-service
uri: http://localhost:8082
predicates:
- Path=/inventory/**
主啟動(dòng)類
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
測(cè)試步驟
- 啟動(dòng) Sentinel Dashboard 和所有服務(wù)(gateway、order-service、inventory-service)。
- 在瀏覽器訪問 Sentinel 控制臺(tái)(http://localhost:8080),添加流控和熔斷規(guī)則。
- 測(cè)試訂單服務(wù)接口:
- 正常請(qǐng)求:http://localhost:8080/orders/create?productId=1
- 模擬超時(shí):http://localhost:8080/orders/create?productId=timeout
總結(jié)
通過以上示例,我們實(shí)現(xiàn)了以下目標(biāo):
1、 基于 Sentinel 的流量控制(FlowRule)和熔斷降級(jí)(DegradeRule)。
2、 使用注解和手動(dòng)規(guī)則配置,實(shí)現(xiàn)服務(wù)間調(diào)用的流量管控。 3、 利用 Gateway 統(tǒng)一流量入口,實(shí)現(xiàn)跨服務(wù)的高效監(jiān)控。
你可以在此基礎(chǔ)上擴(kuò)展更多規(guī)則,比如熱點(diǎn)參數(shù)限流、系統(tǒng)保護(hù)規(guī)則等,進(jìn)一步增強(qiáng)系統(tǒng)的魯棒性和穩(wěn)定性。