跳到主要内容

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 控制台
  • 配置关键指标的告警
  • 定期检查规则配置

下一步