在企业级微服务开发中,sentinel 解决的是系统稳定性问题。
一、sentinel 核心概念与目标
sentinel(分布式系统的流量防卫兵)是阿里巴巴开源的一套面向分布式服务架构的流量控制、熔断降级、系统负载保护的组件。
它的核心目的是保护应用,确保服务在面对高并发、突发流量或依赖服务不可用时,仍能保持高可用性和稳定性,避免因局部故障导致整个系统雪崩。
1-1. 核心概念
| 概念 | 描述 | 作用 |
| 资源 (resource) | sentinel 中最核心的概念。可以是任何您希望保护的代码块、服务、方法、接口等。用唯一名称标识。 | 定义流量防护的目标。 |
| 规则 (rule) | 为资源定义的具体保护措施,如流量阈值、降级策略等。 | 定义如何保护资源(限流、降级、系统保护)。 |
| slot chain | sentinel 的核心处理链。当请求流经资源时,会依次经过统计、限流、熔断等各个 slot(插槽)进行处理。 | sentinel 工作的底层机制。 |
1-2、流量防护三大核心功能:
sentinel 提供了三大保护功能,都基于对资源的实时统计。
1. 🚦 流量控制 (flow control)
这是 sentinel 最基本也是最重要的功能,目的是控制对资源的请求速度,确保其不超过系统的处理能力。
- 指标: 通常基于 qps(每秒查询数)或并发线程数。
- 示例规则: 资源
getproductinfo的 qps 阈值为 200,当超过 200 qps 时,后续请求将被拒绝(默认是failfast策略)。
2. ⚡ 熔断降级 (degrade)
当依赖的资源或服务不稳定(响应慢或失败率高)时,sentinel 会自动切断调用(熔断),让请求快速失败,而不是继续堆积,避免拖垮自身服务。
- 策略:
- 慢调用比例 (rt): 当资源的平均响应时间(rt)超过某个阈值,并且请求量也达到一定值时,触发熔断。
- 异常比例: 当资源的异常请求比例达到阈值时,触发熔断。
- 异常数: 在一个时间窗口内,异常请求总数达到阈值时,触发熔断。
- 熔断器状态: 正常 -> 打开 (open) -> 半开 (half-open) -> 正常。熔断打开后,在设定的恢复时间窗后进入半开状态尝试放行少量请求。
3. 🛡️ 系统保护 (system protection)
从整个系统的维度进行负载保护,而不是针对单个资源。它基于系统的整体负载指标(如 cpu 利用率、系统 load、平均 rt 等)进行判断和限流。
- 作用: 防止系统压力过大时,雪崩式地拒绝所有请求,保护核心业务,同时保证非核心业务的快速失败。
二、sentinel 快速入门步骤(基于 spring cloud/springboot)
步骤一:部署 sentinel dashboard (tc)
sentinel 的规则和监控信息通常通过控制台(dashboard)来配置和查看。
- 下载: 从 sentinel github 或 maven central 下载最新的
sentinel-dashboard.jar。 - 启动: 运行 dashboard。默认端口是
8080。 java -dserver.port=8080 -dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
- 访问: 浏览器访问
http://localhost:8080,默认账号/密码是sentinel/sentinel。
步骤二:集成到业务微服务
引入依赖: 在需要进行流量防护的微服务中引入 sentinel 依赖(推荐使用 spring cloud alibaba 提供的 starter)。
<dependency>
<groupid>com.alibaba.cloud</groupid>
<artifactid>spring-cloud-starter-alibaba-sentinel</artifactid>
</dependency>配置客户端: 在 application.properties 或 application.yml 中配置服务名和 dashboard 地址。
# application.yml
spring:
application:
name: your-service-name
# 配置 sentinel dashboard 地址
cloud:
sentinel:
transport:
dashboard: localhost:8080定义资源 (resource):
import com.alibaba.csp.sentinel.annotation.sentinelresource;
@service
public class orderservice {
// 使用 @sentinelresource 保护方法
@sentinelresource(value = "createorder",
blockhandler = "handleblock", // 违背限流/降级规则时调用的方法
fallback = "handlefallback") // 业务异常时调用的方法
public string createorder(string userid) {
// 核心业务逻辑
return "order created successfully";
}
// 限流或降级时的处理逻辑(参数要匹配原方法)
public string handleblock(string userid, blockexception ex) {
system.out.println("blocked by sentinel: " + ex.getmessage());
return "system busy, please try later.";
}
// 业务异常时的处理逻辑(throwable 参数)
public string handlefallback(string userid, throwable ex) {
system.out.println("service logic error: " + ex.getmessage());
return "internal error occurred.";
}
}- 自动定义 (automatic): sentinel 会自动将 http 接口、feign 客户端调用、dubbo 接口等识别为资源。
- 手动定义 (manual): 使用
@sentinelresource注解来保护您代码中的关键业务逻辑。 - 配置规则:
- 启动您的微服务并调用几次被
@sentinelresource保护的方法。(懒加载) - 登录 sentinel dashboard,在左侧菜单找到您的服务。
- 进入 簇点链路 找到您定义的资源(如
createorder),然后点击右侧的 新增限流 或 新增降级 规则。
- 启动您的微服务并调用几次被
- 例如: 设置
createorder的 qps 阈值 为 10,流控模式 为 快速失败 (fail fast)。
企业级最佳实践
- 持久化规则: dashboard 配置的规则默认只存在内存中,重启后丢失。企业级应用必须将规则持久化到配置中心(如 nacos、apollo),以确保规则的动态性和持久性。
- 区分降级和限流处理:
blockhandler:处理 sentinel 规则 导致的异常(限流、降级、系统保护)。fallback:处理 业务代码 执行时抛出的异常(如数据库连接失败、空指针等)。
- 统一入口: 对外部提供的 api gateway 接口是最重要的限流资源,应优先配置保护。
三、@sentinelresource一般是加在哪里?
@sentinelresource是sentinel的限流降级注解。
3-1、加在哪里
1. service层方法(最常见)
@service
public class orderservice {
@sentinelresource(
value = "createorder",
blockhandler = "handlecreateorderblock",
fallback = "createorderfallback"
)
public order createorder(order order) {
// 业务逻辑
return ordermapper.insert(order);
}
// 处理限流(blockexception)
public order handlecreateorderblock(order order, blockexception e) {
log.warn("订单创建被限流了");
return null;
}
// 处理熔断降级(业务异常)
public order createorderfallback(order order, throwable e) {
log.warn("订单创建失败,执行降级方案");
return new order(); // 返回默认值
}
}2. controller层方法
@restcontroller
@requestmapping("/api/orders")
public class ordercontroller {
@autowired
private orderservice orderservice;
@postmapping
@sentinelresource(
value = "createorderapi",
blockhandler = "handleblock"
)
public apiresponse<order> createorder(@requestbody order order) {
order result = orderservice.createorder(order);
return apiresponse.success(result);
}
public apiresponse<order> handleblock(order order, blockexception e) {
return apiresponse.fail("系统繁忙,请稍后再试");
}
}3. feign客户端方法
@feignclient(name = "stock-service", fallback = stockservicefallback.class)
public interface stockserviceclient {
@postmapping("/api/stock/deduct")
@sentinelresource(
value = "deductstock",
fallback = "deductstockfallback"
)
stock deductstock(@requestparam long productid, @requestparam integer quantity);
default stock deductstockfallback(long productid, integer quantity) {
log.warn("库存服务调用失败,执行降级");
return new stock();
}
}4. 异步方法
@service
public class asyncorderservice {
@async
@sentinelresource(
value = "asyncprocessorder",
blockhandler = "handleasyncblock"
)
public void processorderasync(order order) {
// 异步处理逻辑
dosomeheavywork(order);
}
public void handleasyncblock(order order, blockexception e) {
log.warn("异步处理被限流");
}
}3-2、一般不加的地方
❌ 不加在mapper层
// 错误示范
@mapper
public interface ordermapper {
@sentinelresource("selectorder") // ❌ 不要加这儿
order selectbyid(long id);
}
// 原因:
// 1. mapper直接操作数据库,没有业务逻辑
// 2. 限流应该在业务层面
// 3. 多个service可能调用同一个mapper❌ 不加在private私有方法
@service
public class orderservice {
@sentinelresource("privatemethod") // ❌ 不要加
private void privatemethod() {
// ...
}
// 原因:sentinel是通过代理实现的,私有方法代理不了
}❌ 不加在构造方法
@service
public class orderservice {
@sentinelresource("constructor") // ❌ 不要加
public orderservice() {
// ...
}
}❌ 不加在static方法
@service
public class orderservice {
@sentinelresource("staticmethod") // ❌ 不要加
public static void staticmethod() {
// ...
}
// 原因:static方法不能被代理
}3-3、最佳实践
推荐做法:service + controller双层
// ===== controller层 =====
@restcontroller
@requestmapping("/api/orders")
public class ordercontroller {
@sentinelresource(
value = "createorderapi", // api级别的限流
blockhandler = "apiblockhandler"
)
@postmapping
public apiresponse<order> createorder(@requestbody order order) {
return apiresponse.success(orderservice.createorder(order));
}
public apiresponse<order> apiblockhandler(order order, blockexception e) {
return apiresponse.fail("api请求过于频繁");
}
}
// ===== service层 =====
@service
public class orderservice {
@sentinelresource(
value = "createorderservice", // 业务级别的限流
blockhandler = "serviceblockhandler",
fallback = "createorderfallback"
)
public order createorder(order order) {
// 实际业务逻辑
return ordermapper.insert(order);
}
public order serviceblockhandler(order order, blockexception e) {
return null; // 限流处理
}
public order createorderfallback(order order, throwable e) {
return new order(); // 降级处理
}
}为什么双层?
用户请求
↓
controller层(@sentinelresource)
├─ 控制http请求的流量
├─ 返回友好的错误信息
└─ 保护系统入口
↓
service层(@sentinelresource)
├─ 控制业务操作的流量
├─ 保护核心业务逻辑
└─ 其他service也可能调用3-4、@sentinelresource 注解参数说明
@sentinelresource(
value = "createorder", // 资源名,必需
blockhandler = "handleblock", // 限流/降级时的处理方法
blockhandlerclass = blockhandlers.class, // 指定外部类
fallback = "fallbackmethod", // 业务异常时的降级方法
fallbackclass = fallbackmethods.class, // 指定外部类
exceptionstoignore = {ioexception.class} // 忽略的异常
)
public order createorder(order order) {
// ...
}3-5、常见场景总结
| 场景 | 位置 | 用途 |
|---|---|---|
| 保护http接口 | controller | 限制请求频率 |
| 保护业务方法 | service | 限制业务操作 |
| 远程调用降级 | feign客户端 | 调用失败降级 |
| 异步任务保护 | @async方法 | 限制异步线程 |
| 定时任务保护 | @scheduled方法 | 限制定时任务 |
简单总结:加在service和controller的public业务方法上,不要加在mapper、私有方法、static方法。
到此这篇关于spring cloud sentinel入门讲解的文章就介绍到这了,更多相关spring cloud sentinel入门内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论