在分布式系统中,随着服务的逐渐增多,稳定性和容错性变得至关重要。为了保证系统的高可用性,限流、熔断、降级等机制成为了开发者必不可少的工具。
Sentinel 作为阿里巴巴开源的一款流量防护组件,为微服务提供了流量控制、熔断降级、系统负载保护、实时监控等功能,广泛应用于 Spring Cloud 和 Dubbo 生态中。
一、核心功能
1.流量控制:
- QPS限流:基于每秒请求数量进行限流。
- 并发线程数限流:限制某个资源的并发访问线程数。
- 阈值类型:包括直接拒绝、排队等待等。
2.熔断降级:
- 响应时间:根据资源的平均响应时间来进行熔断。
- 异常比例:当某个资源的异常比例达到设定阈值时,触发熔断。
- 异常数:基于异常数量来触发熔断。
3.系统保护:
- 根据系统的 Load 系数、CPU、线程数等自动限流,确保系统处于健康状态。
4.热点参数限流:
- 根据请求参数的热点值(如商品 ID)进行流量限制。
5.授权规则:
- 通过控制资源访问权限来保护系统资源的一种规则。
二、Spring Cloud 中集成 Sentinel
在 Spring Cloud 中集成 Sentinel 非常简单,通过 Spring Cloud Alibaba 提供的自动化配置,开发者可以快速在项目中引入 Sentinel 的保护机制。
1. 添加 Maven 依赖
首先,在你的 Spring Cloud 项目的 pom.xml 中添加以下依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.8</version>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-dubbo-adapter</artifactId>
<version>1.8.2</version>
</dependency>
2. 在 application.yml 中配置 Sentinel
配置文件中需要定义与 Sentinel 控制台通信的配置,以及与 Dubbo 相关的基本配置:
spring:
application:
name: sentinel-demo
cloud:
sentinel:
transport:
dashboard: localhost:8080 # Sentinel 控制台地址
port: 8719 # 服务与 Sentinel 控制台的通信端口
filter:
enabled: true # 开启 Sentinel 对 Spring MVC 的保护,默认为 false
datasource:
# 自定义的规则名称,可以配置一种规则或多种规则进行流控管理
ds1:
# 从nacos中取相应的配置
nacos:
server-addr: localhost:8848 # Nacos 配置中心的地址
username: xxx # Nacos 配置中心的用户名
password: xxx # Nacos 配置中心的密码
namespace: xxx # Nacos 配置中心的命名空间
dataId: sentinel-rules # Nacos 配置中心中的配置文件 ID,可以统一使用一套,也可以每个服务单独配置,例如${spring.application.name}-sentinel-rules
groupId: DEFAULT_GROUP # 配置文件所属的组
rule-type: flow # 规则类型为流量控制规则
data-type: json # 配置数据的格式为 JSON
ds2:
nacos:
server-addr: localhost:8848
username: xxx
password: xxx
namespace: xxx
dataId: degrade-rules # Nacos 配置中心中的配置文件 ID
groupId: DEFAULT_GROUP
rule-type: degrade # 规则类型为熔断规则
data-type: json
ds3:
nacos:
server-addr: localhost:8848
username: xxx
password: xxx
namespace: xxx
dataId: system-rules # Nacos 配置中心中的配置文件 ID
groupId: DEFAULT_GROUP
rule-type: system # 规则类型为系统规则
data-type: json
dubbo:
application:
name: dubbo-provider
registry:
address: zookeeper://localhost:2181 # 注册中心地址,使用 Zookeeper
protocol:
name: dubbo # 协议名称
port: 20880 # Dubbo 服务端口
三、Dubbo RPC 接口的限流与熔断配置
1. 创建 Dubbo 服务接口及实现类
接下来,创建一个 Dubbo 服务接口和实现类,并使用 @SentinelResource 注解来配置限流和熔断策略。
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.apache.dubbo.config.annotation.DubboService;
import com.alibaba.csp.sentinel.slots.block.BlockException;
public interface GreetingService {
String greet(String name); // 定义服务接口方法
}
@DubboService // 声明 Dubbo 服务
public class GreetingServiceImpl implements GreetingService {
@Override
@SentinelResource(value = "greet", blockHandler = "handleBlock")
public String greet(String name) {
// 业务逻辑代码,返回问候语
return "Hello, " + name;
}
// 限流或熔断时的处理方法
public String handleBlock(String name, BlockException ex) {
// 当触发限流或熔断时,返回的处理信息
return "Request blocked: " + ex.getClass().getSimpleName();
}
}
在这个示例中,@SentinelResource 注解的 value 属性指定了资源名称为 greet,并且指定了当限流或熔断时调用的处理方法 handleBlock。
2. 通过 Sentinel 控制台配置限流规则
Sentinel 控制台可以方便地管理和配置流控规则。
-
启动 Sentinel 控制台:下载并启动 Sentinel 控制台 JAR 包。
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
-
访问控制台并配置规则:登录 Sentinel 控制台,选择你的应用并添加流控规则。
资源名:greet (与 @SentinelResource 中的 value 值一致)
限流模式:QPS
限流阈值:例如设置为 10,表示当 greet 方法的每秒请求超过 10 次时,触发限流。
四、测试限流与熔断效果
1. 启动项目并测试
启动你的 Spring Cloud 项目,使用 Dubbo 客户端进行 RPC 调用。当并发请求超过设定的限流阈值时,将触发限流,客户端将收到 handleBlock 方法返回的信息。
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@DubboReference(version = "1.0.0")
private GreetingService greetingService; // 引用 Dubbo 服务
@GetMapping("/greet")
public String greet(String name) {
// 调用 Dubbo 服务的 greet 方法
return greetingService.greet(name);
}
}
访问 http://localhost:8080/greet?name=World,当访问频率过高时,应该会收到 Request blocked 的返回信息。
五、Controller 方法的限流与熔断配置
Sentinel 也可以对 Spring Boot 项目中的 Controller 方法进行限流,其使用方式与Dubbo接口限流的方式基本一致。
@RestController
public class TestController {
@GetMapping("/test")
@SentinelResource(value = "testResource", blockHandler = "handleBlock")
public String test() {
return "Hello Sentinel!";
}
public String handleBlock(BlockException ex) {
return "Request blocked due to flow control";
}
}
六、通过 Nacos 动态管理限流规则
为了更灵活地管理和调整限流规则,可以通过 Nacos 配置中心实现规则的动态管理。
1.在 Nacos 中创建配置文件
登录 Nacos 控制台,创建一个新的配置文件sentinel-rules,内容如下:
[
{
"resource": "greet", //资源名称
"limitApp": "default", // 限制应用,default 表示对所有应用生效
"grade": 1, // 限流阈值类型,0表示线程数,1表示QPS
"count": 10, // 阈值
"strategy": 0, // 流控模式,0表示直接,1表示关联,2表示链路
"controlBehavior": 0, // 流控效果,0表示快速失败,1表示Warm Up,2表示排队等待(Warm Up 是指一种流控策略,中文通常翻译为“预热”或“暖备”。具体来说,Warm Up 机制用于在系统在一定时间内逐渐增加流量阈值,而不是立即将流量限制在最大阈值上,以防止系统在刚开始承受高流量时出现负载过大的情况。)
"warmUpPeriodSec": 10, // Warm Up 时长,单位为秒
"maxQueueingTimeMs": 500 // 排队等待最大时长,单位为毫秒
}
]
2.动态加载规则
配置完成后,Sentinel 会自动从 Nacos 拉取最新的规则并应用到系统中。
七、其他规则类型
Sentinel 提供了五种主要的规则配置:流量控制规则、降级规则、系统规则、热点参数规则和授权规则。每种规则都有其特定的配置项。刚才已经使用过流量控制规则,下面介绍其它四种规则。
降级规则配置(Degrade Rules)
降级规则用于熔断降级,当请求的错误率或响应时间超过设定的阈值时,可以触发降级(所以没有controlBehavior配置)。
基本配置项:
spring:
cloud:
sentinel:
datasource:
degrade:
nacos:
server-addr: localhost:8848
dataId: degrade-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: degrade
规则内容(JSON 格式)
[
{
"resource": "exampleResource", // 资源名称
"grade": 1, // 熔断策略,0表示慢调用比例,1表示异常比例,2表示异常数
"count": 1000, // 阈值(当 grade=0 时为 RT,单位为 ms;当 grade=1 时为异常比例;当 grade=2 时为异常数)
"timeWindow": 10, // 熔断持续时间,单位为秒
"minRequestAmount": 5, // 最小请求数
"statIntervalMs": 1000 // 统计时长,单位为毫秒
}
]
系统规则配置(System Rules)
系统规则用于全局的系统保护,防止整个系统因资源超载而崩溃。当触发系统规则的某一项(如 QPS、线程数、CPU 使用率等)达到设定的阈值时,Sentinel 会直接拒绝新进入的请求。
基本配置项
spring:
cloud:
sentinel:
datasource:
system:
nacos:
server-addr: localhost:8848
dataId: system-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: system
规则内容(JSON 格式)
[
{
"avgRt": 1000, // 全局平均响应时间阈值,单位为毫秒
"maxThread": 20, // 全局最大线程数
"qps": 500, // 全局QPS阈值
"cpuUsage": 0.8, // 全局CPU使用率阈值,取值范围 0.0-1.0
"highestSystemLoad": 5 // 系统负载阈值,仅在 Linux/Unix 上生效
}
]
热点参数规则配置(Hot Param Rules)
热点参数规则用于限制某个资源的某个参数的热点频次,防止某个特定参数(如用户ID)过热。
基本配置项
spring:
cloud:
sentinel:
datasource:
param-flow:
nacos:
server-addr: localhost:8848
dataId: param-flow-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: param-flow
规则内容(JSON 格式)
[
{
"resource": "exampleResource", // 资源名称
"paramIdx": 0, // 参数索引,指定对第几个参数进行限流,从 0 开始
"count": 100, // 限流阈值
"grade": 1, // 限流等级,1表示QPS
"controlBehavior": 0, // 控制行为,0表示快速失败,1表示Warm Up,2表示排队等待
"paramFlowItemList": [
{
"object": "exampleValue", // 参数值
"classType": "java.lang.String", // 参数类型
"count": 10 // 对应的限流阈值
}
]
}
]
授权规则配置(Authority Rule)
授权规则是通过控制资源访问权限来保护系统资源的一种规则。它主要用于防止非法用户或未授权的请求访问指定资源,从而提供更加精细的安全管理。
基本配置项
spring:
cloud:
sentinel:
datasource:
param-flow:
nacos:
server-addr: localhost:8848
dataId: authority-rules
groupId: DEFAULT_GROUP
data-type: json
rule-type: authority
规则内容(JSON 格式)
[
{
"resource": "testApi",
"limitApp": "appA",
"strategy": 0 // 白名单模式
},
{
"resource": "testApi",
"limitApp": "appB",
"strategy": 1 // 黑名单模式
}
]
八、与Hystrix的差异
Sentinel 和 Hystrix 是用于实现熔断、限流和容错处理的两个常用工具。尽管它们在功能上有一些重叠,但它们在设计理念、功能特点和应用场景上有许多不同之处。以下是 Sentinel 和 Hystrix 的主要不同点:
设计理念
Sentinel
- Sentinel 的设计理念是“全方位流量防护”。它不仅关注熔断和降级,还涵盖了流量控制、热点参数限流、系统保护等多个维度,旨在提供全方位的流量管理和系统保护。
Hystrix
- Hystrix 的设计理念是“防止服务之间的故障传播”。它专注于熔断、降级和线程隔离,通过这些手段防止单个服务的故障扩散到整个系统。
社区状态
Sentinel
- 活跃开发:Sentinel 由阿里巴巴开源,社区非常活跃,定期发布更新和新功能,特别是在国内有广泛的使用和支持。
Hystrix
- 进入维护状态:Hystrix 由 Netflix 开源,但目前已经进入维护状态,不再积极开发新功能。Netflix 也推荐开发者转向其他替代方案,如 Resilience4j。
性能开销
Sentinel
- 轻量级:Sentinel 在流控和熔断的实现上相对轻量,具有较高的性能,特别适合高并发场景。
Hystrix
- Hystrix 的线程池隔离机制虽然有效,但也带来了一定的性能开销,尤其是在高并发场景下,可能会出现线程池耗尽的问题。
总的来说,Sentinel 是一个功能全面、扩展性强、适合复杂场景的流控和熔断解决方案,特别适用于需要多维度保护和实时动态调整的系统。
而 Hystrix 则专注于熔断和降级,适合简单的容错需求,但由于已进入维护状态,可能不适合长期使用或新项目的开发。
总结
Sentinel 为微服务架构中的限流、熔断等容错机制提供了强大的支持。通过在 Spring Cloud 中集成 Sentinel,可以轻松实现对服务的流量控制和稳定性保障。
通过合理地配置和使用 Sentinel,可以显著提高分布式系统的稳定性和容错能力,确保在高并发场景下系统依然能够平稳运行。