实现分布式系统的高效流量管控是微服务架构中非常重要的一环。下面以 Spring Boot 和 Spring Cloud 框架为例,通过阿里巴巴的 Sentinel 组件实现多服务环境下的流量监控与管控。我们将展示如何使用 Sentinel 配置流控规则、实现熔断降级和跨服务流量管控,同时包含完整的代码和配置。
系统设计目标
- 模拟一个微服务架构:订单服务(order-service)和库存服务(inventory-service)。
- Sentinel 的核心功能:
- 在每个服务上设置流控规则,限制流量请求。
- 实现跨服务调用时的流量监控。
- 配置熔断降级规则,确保系统的稳定性。
- 提供完整的整合代码,包括服务配置、Sentinel 规则代码和流量控制逻辑。
系统架构图
用户请求 -> Gateway(网关) -> Order-Service -> Inventory-Service
流控目标:
- 限制 order-service 的并发访问数为 10。
- 对 inventory-service 的 QPS 设置为 5。
- 配置熔断规则,若 inventory-service 超时率超过 50%,熔断 10 秒。
- 在 Sentinel Dashboard 上实时监控流量数据。
准备工作
依赖引入
在所有服务中需要添加以下依赖。
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 下载
下载并启动 Sentinel 控制台(建议使用最新版本):
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
核心服务实现
1、Order-Service(订单服务)
订单服务负责接收用户订单请求,并调用库存服务扣减库存。
application.yml 配置
server:
port: 8081
spring:
application:
name: order-service
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 指定 Sentinel Dashboard 地址
port: 8719 # 服务与 Sentinel Dashboard 的通信端口
management:
endpoints:
web:
exposure:
include: '*'
主启动类
@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) {
// 调用库存服务扣减库存
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.";
}
}
流控规则配置
@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(库存服务)
库存服务负责处理库存扣减请求。
application.yml 配置
server:
port: 8082
spring:
application:
name: inventory-service
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8720
management:
endpoints:
web:
exposure:
include: '*'
主启动类
@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) {
// 模拟业务处理
if ("timeout".equals(productId)) {
try {
Thread.sleep(2000); // 模拟超时
} 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.";
}
}
熔断规则配置
@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); // 基于响应时间熔断
rule.setCount(1000); // 超时阈值(ms)
rule.setTimeWindow(10); // 熔断持续时间(秒)
rule.setMinRequestAmount(5); // 最小请求数
rule.setStatIntervalMs(60000); // 统计时间窗口(ms)
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
3、Gateway(网关服务)
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/**
主启动类
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
测试步骤
- 启动 Sentinel Dashboard 和所有服务(gateway、order-service、inventory-service)。
- 在浏览器访问 Sentinel 控制台(http://localhost:8080),添加流控和熔断规则。
- 测试订单服务接口:
- 正常请求:http://localhost:8080/orders/create?productId=1
- 模拟超时:http://localhost:8080/orders/create?productId=timeout
总结
通过以上示例,我们实现了以下目标:
1、 基于 Sentinel 的流量控制(FlowRule)和熔断降级(DegradeRule)。
2、 使用注解和手动规则配置,实现服务间调用的流量管控。 3、 利用 Gateway 统一流量入口,实现跨服务的高效监控。
你可以在此基础上扩展更多规则,比如热点参数限流、系统保护规则等,进一步增强系统的鲁棒性和稳定性。