Spring Cloud Alibaba 整合
Spring Cloud Alibaba 提供了 Sentinel 的开箱即用整合,可以快速为 Spring Cloud 应用添加流量控制和熔断降级能力。
引入依赖
在 pom.xml 中添加 Spring Cloud Alibaba Sentinel 依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2022.0.0.0</version>
</dependency>
如果使用 Gradle:
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-sentinel:2022.0.0.0'
基础配置
在 application.yml 中配置 Sentinel:
spring:
application:
name: my-service
cloud:
sentinel:
transport:
dashboard: localhost:8080 # 控制台地址
port: 8719 # 与控制台通信的端口
eager: true # 是否饥饿加载
web-context-unify: true # Web 上下文统一
filter:
enabled: true # 开启 Web Filter
url-patterns: /** # 拦截路径
自动埋点
Spring Cloud Alibaba Sentinel 会自动为以下组件进行埋点:
Web 接口
所有 Controller 的 HTTP 接口会自动被 Sentinel 保护,资源名为 URL 路径:
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
资源名:GET:/api/users/{id}
OpenFeign
使用 OpenFeign 时,每个 Feign 接口会自动被 Sentinel 保护:
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
@Component
public class UserServiceFallback implements UserServiceClient {
@Override
public User getUser(Long id) {
return User.defaultUser();
}
}
需要在配置中开启 Feign 的 Sentinel 支持:
feign:
sentinel:
enabled: true
RestTemplate
使用 @SentinelRestTemplate 注解为 RestTemplate 添加 Sentinel 支持:
@Configuration
public class RestTemplateConfig {
@Bean
@SentinelRestTemplate(blockHandler = "handleBlock", fallback = "handleFallback")
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static ClientHttpResponse handleBlock(HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution,
BlockException ex) {
return new MockClientHttpResponse("系统繁忙".getBytes(), HttpStatus.TOO_MANY_REQUESTS);
}
public static ClientHttpResponse handleFallback(HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution,
Throwable ex) {
return new MockClientHttpResponse("服务降级".getBytes(), HttpStatus.SERVICE_UNAVAILABLE);
}
}
使用注解定义资源
使用 @SentinelResource 注解可以更灵活地定义资源:
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlockHandler",
fallback = "createOrderFallback")
public Order createOrder(OrderRequest request) {
// 业务逻辑
return orderRepository.save(request.toOrder());
}
// 限流或熔断时的处理方法
public Order createOrderBlockHandler(OrderRequest request, BlockException e) {
return Order.builder()
.status("BLOCKED")
.message("系统繁忙,请稍后重试")
.build();
}
// 业务异常时的降级方法
public Order createOrderFallback(OrderRequest request, Throwable t) {
return Order.builder()
.status("FAILED")
.message("服务暂时不可用")
.build();
}
}
注解属性说明:
| 属性 | 说明 |
|---|---|
| value | 资源名称 |
| blockHandler | 限流/熔断时的处理方法名 |
| blockHandlerClass | 处理方法所在的类 |
| fallback | 业务异常时的降级方法名 |
| fallbackClass | 降级方法所在的类 |
| defaultFallback | 默认降级方法名 |
| exceptionsToTrace | 需要追踪的异常类型 |
| exceptionsToIgnore | 需要忽略的异常类型 |
动态规则配置
使用 Nacos 作为规则数据源
添加 Nacos 数据源依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.8.8</version>
</dependency>
配置 Nacos 数据源:
spring:
cloud:
sentinel:
datasource:
# 流控规则
flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow
# 熔断规则
degrade:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
rule-type: degrade
# 系统规则
system:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-system-rules
groupId: SENTINEL_GROUP
rule-type: system
在 Nacos 中创建规则配置,格式为 JSON:
[
{
"resource": "createOrder",
"grade": 1,
"count": 100,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
使用 Apollo 作为规则数据源
添加 Apollo 数据源依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-apollo</artifactId>
<version>1.8.8</version>
</dependency>
配置 Apollo 数据源:
spring:
cloud:
sentinel:
datasource:
flow:
apollo:
namespace-name: application
rule-key: sentinel-flow-rules
default-flow-rule-value: ""
rule-type: flow
完整配置示例
Maven 依赖
<dependencies>
<!-- Spring Cloud Alibaba Sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- Nacos 数据源 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
</dependencies>
配置文件
spring:
application:
name: order-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
dashboard: localhost:8080
port: 8719
eager: true
datasource:
flow:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
rule-type: flow
degrade:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-degrade-rules
groupId: SENTINEL_GROUP
rule-type: degrade
feign:
sentinel:
enabled: true
management:
endpoints:
web:
exposure:
include: "*"
启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
业务代码
@RestController
@RequestMapping("/api/orders")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
@SentinelResource(value = "createOrder",
blockHandler = "createOrderBlockHandler")
public Result<Order> createOrder(@RequestBody OrderRequest request) {
return Result.success(orderService.createOrder(request));
}
public Result<Order> createOrderBlockHandler(OrderRequest request, BlockException e) {
return Result.error("系统繁忙,请稍后重试");
}
}
@Service
public class OrderService {
@Autowired
private UserServiceClient userServiceClient;
@SentinelResource(value = "processOrder",
fallback = "processOrderFallback")
public Order createOrder(OrderRequest request) {
// 调用用户服务
User user = userServiceClient.getUser(request.getUserId());
// 创建订单
Order order = new Order();
order.setUserId(user.getId());
order.setAmount(request.getAmount());
return order;
}
public Order processOrderFallback(OrderRequest request, Throwable t) {
// 降级逻辑
return Order.defaultOrder();
}
}
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserServiceClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
@Component
public class UserServiceFallback implements UserServiceClient {
@Override
public User getUser(Long id) {
return User.defaultUser();
}
}
网关流控
Spring Cloud Gateway 整合 Sentinel 可以实现网关维度的流量控制:
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
配置网关流控
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Configuration
public class GatewayConfiguration {
@Bean
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
@Bean
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler();
}
@PostConstruct
public void init() {
// 自定义限流响应
GatewayCallbackManager.setBlockHandler((exchange, t) -> {
ServerWebExchange serverWebExchange = exchange;
serverWebExchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
serverWebExchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
String result = "{\"code\":429,\"message\":\"系统繁忙,请稍后重试\"}";
DataBuffer buffer = serverWebExchange.getResponse()
.bufferFactory()
.wrap(result.getBytes());
return serverWebExchange.getResponse().writeWith(Mono.just(buffer));
});
}
}
网关流控规则
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import java.util.HashSet;
import java.util.Set;
@Configuration
public class GatewayRuleConfig {
@PostConstruct
public void init() {
Set<GatewayFlowRule> rules = new HashSet<>();
// API 分组限流
rules.add(new GatewayFlowRule("user-api")
.setCount(100)
.setIntervalSec(1));
// 路由 ID 限流
rules.add(new GatewayFlowRule("user-service")
.setCount(50)
.setIntervalSec(1)
.setBurst(20)
.setBurst(20));
GatewayRuleManager.loadRules(rules);
}
}
最佳实践
1. 合理配置资源
- Web 接口使用自动埋点
- 业务方法使用
@SentinelResource注解 - 外部调用使用 Feign 或 RestTemplate 整合
2. 规则持久化
- 使用 Nacos 或 Apollo 存储规则
- 配置动态数据源
- 规则变更实时生效
3. 降级策略
- 提供有意义的降级响应
- 记录降级日志
- 区分限流和业务异常的处理
4. 监控告警
- 接入 Sentinel 控制台
- 配置关键指标的告警
- 定期检查规则配置
下一步
- 速查表 - 查阅常用配置和命令