sentinel基本使用
sentinel基本使用
随着微服务的流行,服务和服务之间的稳定性变得越来越重要
Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性
本地下载安装并启动sentinel
下载地址:https://github.com/alibaba/Sentinel/releases
官方文档:https://sentinelguard.io/zh-cn/docs/flow-control.html
下载后得到一个jar包,进入当前jar包所在目录启动cmd,通过命令启动jar包:
java -jar sentinel-dashboard-1.8.3.jar
浏览器访问:http://localhost:8080/#/login
进入登录页面,输入用户名和密码登录(默认用户名和密码都是sentinel)
sentinel监控服务
导入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
配置文件
spring:
cloud:
sentinel:
transport:
# 配置Sentinel dashboard地址
dashboard: localhost:8080
# Sentinel后台通信端口,默认8719,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
# 监控端口
management:
endpoints:
web:
exposure:
# 暴露所有端口
include: '*'
随便写两个测试接口
package com.yl.sentinel.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* sentinel测试接口
*
* @auther Y-wee
*/
@RestController
@Slf4j
@RequestMapping("/sentinel")
public class FlowLimitController {
/**
* 测试A
*
* @return testA
*/
@GetMapping("/testA")
public String testA() {
return "testA";
}
/**
* 测试B
*
* @return testB
*/
@GetMapping("/testB")
public String testB() {
log.info(Thread.currentThread().getName() + "\t" + "...testB");
return "testB";
}
}
启动服务,发送请求,然后登录sentinel就可以看到相关监控信息
由于sentinel采用懒加载模式,只启动服务是看不到监控信息的,只有发送请求了sentinel才会产生监控信息
sentinel流量控制
资源名:唯一名称,默认请求路径
针对来源:sentinel可以针对调用者进行限流,填写微服务名,默认default(不区分来源)
阈值类型/单机阈值:
- QPS(每秒钟的请求数量):当调用该api的QPS达到阈值的时候,进行限流
- 线程数:当调用该api的线程数达到阈值的时候,进行限流
流控模式:
- 直接:api达到限流条件时,直接限流
- 关联:当关联的资源达到阈值时,就限流自己
- 链路:只记录指定链路上的流量(指定资源从入口资源进来的流量,如果达到阈值,就进行限流)【api级别的针对来源】
流控效果:
- 快速失败:直接失败,抛异常
- Warm Up:根据codeFactor(冷加载因子,默认3)的值,从阈值/codeFactor,经过预热时长,才达到设置的QPS阈值
- 排队等待:匀速排队,让请求以匀速的速度通过,阈值类型必须设置为QPS,否则无效
@SentinelResource配置热点参数限流
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控
要使用热点参数限流功能,需要以下依赖(spring-cloud-starter-alibaba-sentinel依赖包含了以下依赖不需要额外导入):
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-parameter-flow-control</artifactId>
<version>x.y.z</version>
</dependency>
然后为对应的资源配置热点参数限流规则,并在 entry
(入口)的时候传入相应的参数,即可使热点参数限流生效,eg:
package com.yl.sentinel.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.TimeUnit;
/**
* sentinel测试接口
*
* @auther Y-wee
*/
@RestController
@Slf4j
@RequestMapping("/sentinel")
public class FlowLimitController {
/**
* 测试热点参数限流
* 注解@SentinelResource方式定义的资源,若注解作用的方法上有参数
* Sentinel 会将它们作为参数传入 SphU.entry(res, args),从而可以用于热点规则判断
* 注解@SentinelResource的value值为热点规则资源名,blockHandler指定自定义降级方法
* 如果不指定降级方法,触发热点限流规则直接抛出异常
*
* @param p1 参数一
* @param p2 参数二
* @return 结果
*/
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
return "testHotKey";
}
/**
* 降级方法
* 注意:方法参数要加上BlockException
*
* @param p1
* @param p2
* @param exception
* @return
*/
public String deal_testHotKey(String p1, String p2, BlockException exception) {
return "deal_testHotKey,o(╥﹏╥)o";
}
}
sentinel新增热点规则:请求包含第一个参数(参数值不变),且在1s内请求数量超过1时,触发降级方法
上述案例演示了第一个参数p1,当QPS超过1秒1次点击后马上被限流
当有特殊情况,我们希望p1为某个特殊值时,限流值不一样则可以在高级选项中进行配置
@SentinelResource配置流量控制
package com.yl.sentinel.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 注解@SentinelResource配置流量控制
*
* @auther Y-wee
*/
@RestController
@RequestMapping("/sentinel")
public class RateLimitController {
/**
* 测试@SentinelResource配置流量控制
* value:流控规则资源名;blockHandler:降级方法(如果不配置触发流控规则则调用sentinel默认降级方法)
*
* @return 测试结果
*/
@GetMapping("/resource")
@SentinelResource(value = "resource",blockHandler ="handleException" )
public CommonResult byResource() {
return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
}
注意:@SentinelResource不支持私有方法
以上配置降级方法跟接口方法在同一个类,不符合业务逻辑,需要将降级方法写在单独的类中隔离,实现步骤:
编写降级处理类自定义降级方法
package com.yl.sentinel.myhandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.yl.common.entity.CommonResult;
/**
* 自定以降级方法
*
* @auther Y-wee
*/
public class CustomerBlockHandler {
public static CommonResult handlerException(BlockException exception) {
return new CommonResult(4444, "按客戶自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(4444, "按客戶自定义,global handlerException----2");
}
}
controller
package com.yl.sentinel.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import com.yl.sentinel.myhandler.CustomerBlockHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 注解@SentinelResource配置流量控制
*
* @auther Y-wee
*/
@RestController
@RequestMapping("/sentinel")
public class RateLimitController {
/**
* 测试@SentinelResource隔离降级方法
* blockHandlerClass:指定降级方法所在类
*
* @return
*/
@GetMapping("/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler",
blockHandlerClass = CustomerBlockHandler.class,
blockHandler = "handlerException2")
public CommonResult customerBlockHandler() {
return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003"));
}
}
sentinel服务异常降级处理
@SentinelResource中blockHandler处理的是sentinel控制台配置的违规情况会调用降级方法,当有运行异常时,依旧会抛出异常(blockHandler主管配置出错,运行出错该走异常走异常),要处理运行时异常需要用到@SentinelResource中的fallback,总结:
- blockHandler只负责sentinel控制台配置违规
- fallback只负责业务异常
代码实战
package com.yl.sentinel.order.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.yl.common.entity.CommonResult;
import com.yl.common.entity.Payment;
import com.yl.sentinel.order.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @auther Y-wee
*/
@RestController
@Slf4j
@RequestMapping("/order")
public class CircleBreakerController {
public static final String SERVICE_URL = "http://sentinel-payment";
@Resource
private RestTemplate restTemplate;
/**
* fallback指定服务异常时的降级方法
* 如果blockHandler和fallback都配置了
* 服务异常时调用fallback指定的降级方法,违反控流规则时调用blockHandler指定的降级方法
*
* @param id id
* @return result
*/
@RequestMapping("/fallback/{id}")
@SentinelResource(value = "fallback", fallback = "handlerFallback", blockHandler = "blockHandler")
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/payment/get/" + id, CommonResult.class, id);
if (id == 4) {
throw new IllegalArgumentException("IllegalArgumentException,非法参数异常....");
} else if (result.getData() == null) {
throw new NullPointerException("NullPointerException,该ID没有对应记录,空指针异常");
}
return result;
}
/**
* 降级方法
*
* @param id
* @param e
* @return
*/
public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
Payment payment = new Payment(id, "null");
return new CommonResult<>(444, "兜底异常handlerFallback,exception内容 " + e.getMessage(), payment);
}
/**
* 降级方法
*
* @param id
* @param blockException
* @return
*/
public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
Payment payment = new Payment(id, "null");
return new CommonResult<>(445, "blockHandler-sentinel限流,无此流水: blockException " + blockException.getMessage(), payment);
}
}
扩展
/**
* exceptionsToIgnore:顾名思义,当触发指定异常(IllegalArgumentException),不调用降级方法直接将异常抛出
*/
@SentinelResource(value = "fallback",
fallback = "handlerFallback",
blockHandler = "blockHandler",
exceptionsToIgnore = {IllegalArgumentException.class})
如果需要sentinel结合feign使用,则要在配置文件开启sentinel对feign的支持:
# 激活Sentinel对Feign的支持
feign:
sentinel:
enabled: true
sentinel持久化配置
如果没有配置sentinel持久化,服务重启,sentinel规则将消失,需要重启配置
将流控规则持久化进nacos保存,服务重启,sentinel流控规则持续有效,配置如下:
导入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
配置文件
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
port: 8719
datasource:
ds1:
nacos:
server-addr: localhost:8848
dataId: sentinel
groupId: DEFAULT_GROUP
# 配置文件类型
data-type: json
rule-type: flow
nacos新建配置文件,Data ID:sentinel、Group:DEFAULT_GROUP、配置格式:JSON、配置内容如下:
[
{
// 资源名称
"resource":"/sentinel/testA",
// 来源应用
"limitApp":"default",
// 阈值类型,0-线程数,1-QPS
"grade":1,
// 单机阈值
"count":1,
// 流控模式,0-直接,1-关联,2-链路
"strategy":0,
// 流控效果,0-快速失败,1-Warm Up,2-排队等待
"controlBehavior":0,
// 是否集群
"clusterMode":false
}
]
nacos配置时把注释删除,防止报格式错误
配置完成,服务重启,流控规则不会消失
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2021-03-24 springboot项目pom文件配置