Appearance
Sentinel服务熔断与限流
Sentinel 是阿里巴巴开源的面向分布式服务架构的轻量级流量控制组件,主要以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。Spring Cloud Alibaba Sentinel 提供了 Spring Cloud 标准的服务熔断与限流实现。
Sentinel 核心功能
Sentinel 具有以下核心功能:
- 流量控制:根据系统负载和调用方式控制流量
- 熔断降级:当调用链路中某个资源出现问题时,暂时切断对该资源的调用
- 系统负载保护:根据系统指标(如 CPU 使用率、系统负载)动态调整流量
- 实时监控:提供实时的监控和统计功能
- 规则持久化:支持规则的动态配置和持久化
安装与部署 Sentinel 控制台
Sentinel 控制台是流量控制、熔断降级规则统一配置和管理的界面,也可以查看监控和实时规则。
方式一:从 GitHub 下载 jar 包
- 从 GitHub Releases 下载 jar 包
- 运行控制台:bash
java -Dserver.port=8080 -jar sentinel-dashboard-1.8.5.jar
方式二:使用 Docker
bash
docker run --name sentinel -d -p 8858:8858 bladex/sentinel-dashboard:latest
启动后,可以通过浏览器访问控制台:
http://localhost:8858
默认用户名和密码都是 sentinel
。
整合 Spring Boot 应用
1. 添加依赖
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
2. 配置应用
在 application.properties
或 application.yml
中添加配置:
yaml
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8858 # Sentinel 控制台地址
port: 8719 # 应用与 Sentinel 控制台通信端口,默认为 8719
eager: true # 取消懒加载,即服务启动时就初始化 Sentinel
3. 定义资源
Sentinel 中的资源是保护的对象,可以是任何代码块。最常见的资源是 Spring MVC 的接口方法和 OpenFeign 客户端方法。
方式一:使用 @SentinelResource
注解定义资源
java
@RestController
public class HelloController {
@GetMapping("/hello")
@SentinelResource(value = "hello",
blockHandler = "helloBlockHandler",
fallback = "helloFallback")
public String hello(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("参数不能为空");
}
return "Hello, " + name;
}
// 处理限流或降级
public String helloBlockHandler(String name, BlockException ex) {
log.warn("限流,资源名:{}", ex.getRule().getResource(), ex);
return "系统繁忙,请稍后再试";
}
// 处理业务异常
public String helloFallback(String name, Throwable t) {
log.error("接口调用异常", t);
return "服务异常,请稍后再试";
}
}
在上面的例子中:
value
指定资源名称blockHandler
指定被限流/降级/系统保护时的处理函数fallback
指定业务异常时的处理函数
方式二:Spring MVC 和 OpenFeign 的自动资源定义
对于 Spring MVC 控制器和 OpenFeign 客户端,Sentinel 会自动将它们定义为资源,无需额外配置。
Spring MVC 控制器资源名规则:{HTTP_METHOD}:{requestPattern}
,如 GET:/hello
。
OpenFeign 客户端资源名规则:{ServiceName}:{MethodSignature}
,如 user-service:getUserById(Long)
。
4. 配置流量控制规则
规则可以通过代码、控制台或配置文件进行配置。
方式一:通过代码配置
java
@PostConstruct
public void initFlowRules() {
List<FlowRule> rules = new ArrayList<>();
// 创建流控规则
FlowRule rule = new FlowRule();
rule.setResource("hello"); // 资源名
rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 限流阈值类型(QPS)
rule.setCount(10); // 每秒允许10个请求
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
方式二:通过控制台配置
在 Sentinel 控制台的"流控规则"页面,点击"新增流控规则"按钮,填写相关信息后保存。
方式三:通过配置文件配置
yaml
spring:
cloud:
sentinel:
datasource:
ds1:
file:
file: classpath:sentinel/flow-rule.json
data-type: json
rule-type: flow
JSON 配置示例:
json
[
{
"resource": "hello",
"limitApp": "default",
"grade": 1,
"count": 10,
"strategy": 0,
"controlBehavior": 0
}
]
流量控制详解
流控模式
Sentinel 支持三种流控模式:
- 直接模式(默认):直接对资源限流
- 关联模式:当关联的资源达到阈值时,限流自己
- 链路模式:对从指定入口进来的流量限流
流控效果
Sentinel 支持三种流控效果:
- 快速失败(默认):直接拒绝请求
- Warm Up:预热/冷启动,逐渐增加流量
- 排队等待:请求匀速通过,多余的请求排队等待
流控规则属性
流控规则主要包含以下属性:
属性 | 说明 | 可选值 |
---|---|---|
resource | 资源名 | - |
count | 限流阈值 | - |
grade | 限流阈值类型 | QPS(1)、并发线程数(0) |
limitApp | 流控针对的调用来源 | default 表示不区分调用来源 |
strategy | 调用关系限流策略 | 直接(0)、关联(1)、链路(2) |
controlBehavior | 流控效果 | 快速失败(0)、Warm Up(1)、排队等待(2) |
clusterMode | 是否集群限流 | true/false |
熔断降级详解
熔断策略
Sentinel 支持三种熔断策略:
- 慢调用比例:当调用时间超过阈值的请求比例达到设定值时触发熔断
- 异常比例:当资源的每秒异常总数占通过量的比例超过阈值时触发熔断
- 异常数:当资源近一分钟的异常数目超过阈值时触发熔断
熔断规则配置
java
@PostConstruct
public void initDegradeRules() {
List<DegradeRule> rules = new ArrayList<>();
// 创建熔断规则
DegradeRule rule = new DegradeRule();
rule.setResource("hello"); // 资源名
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_RATIO); // 熔断策略(异常比例)
rule.setCount(0.5); // 异常比例阈值,范围是 [0.0, 1.0]
rule.setTimeWindow(10); // 熔断时长,单位为秒
rule.setMinRequestAmount(5); // 熔断触发的最小请求数
rule.setStatIntervalMs(1000); // 统计时长,单位为毫秒
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
系统自适应保护
Sentinel 支持系统自适应保护,根据系统的负载情况自动调整流量。
java
@PostConstruct
public void initSystemRules() {
List<SystemRule> rules = new ArrayList<>();
// 设置系统保护规则
SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10); // 最大系统负载
rule.setAvgRt(5000); // 所有入口流量的平均响应时间
rule.setMaxThread(200); // 入口流量的最大并发数
rule.setQps(2000); // 所有入口资源的 QPS
rule.setCpuUsageRatio(0.8); // CPU 使用率
rules.add(rule);
SystemRuleManager.loadRules(rules);
}
整合 OpenFeign
当使用 Sentinel 整合 OpenFeign 时,需要在配置中开启 Sentinel 支持:
yaml
feign:
sentinel:
enabled: true
然后为 Feign 客户端定义回退类:
java
@FeignClient(name = "user-service", fallback = UserServiceFallback.class)
public interface UserService {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
@Component
public class UserServiceFallback implements UserService {
@Override
public User getUserById(Long id) {
return new User(id, "默认用户", 0);
}
}
规则持久化
为了防止规则在应用重启后丢失,Sentinel 支持将规则持久化到外部数据源。
整合 Nacos 实现规则持久化
xml
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
配置 Nacos 数据源:
yaml
spring:
cloud:
sentinel:
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: ${spring.application.name}-flow-rules
groupId: SENTINEL_GROUP
data-type: json
rule-type: flow
常见问题及解决方案
控制台无法显示应用实例
- 检查应用与控制台的网络连通性
- 确认
spring.cloud.sentinel.transport.dashboard
配置正确 - 确认端口未被防火墙阻止
流控规则不生效
- 检查资源名称是否与规则中定义的一致
- 查看应用日志,确认规则是否正确加载
- 尝试通过代码方式设置规则,验证功能是否正常
预热模式下流量不符合预期
预热模式(Warm Up)下,冷启动期间允许通过的 QPS 是设置的阈值的 1/3,然后逐渐增加到设定的阈值。确认 warmUpPeriodSec
参数设置合理。
Fallback 和 BlockHandler 的区别
fallback
:处理业务异常,如超时、网络异常等blockHandler
:处理 Sentinel 控制台配置的规则触发的限流、熔断等
正确区分这两种情况,可以更精细地处理不同类型的异常。
最佳实践
- 明确资源定义边界:资源定义要明确,粒度要合适,过大或过小都不利于流控和熔断
- 灵活使用不同的流控模式:根据业务场景选择合适的流控模式
- 合理设置熔断条件:熔断条件既不能过于宽松(减弱保护能力),也不能过于严格(影响正常业务)
- 实现细粒度的 fallback:为不同的异常场景实现不同的 fallback 逻辑
- 持久化规则配置:使用 Nacos 等保存规则配置,避免规则丢失
- 结合监控系统:与 Prometheus、Grafana 等监控系统结合,实时监控系统状态
- 分布式限流:对于分布式环境,考虑使用集群限流功能
总结
Sentinel 作为 Spring Cloud Alibaba 的重要组件,提供了全面的流量控制、熔断降级和系统保护功能,有效保障了微服务的稳定性和可靠性。相比于 Hystrix,Sentinel 提供了更多的流控模式和效果,以及更直观的监控和配置界面,成为微服务保护的强大工具。