文章目录
- sentinel
- sentinel介绍
- 重要的核心概念
- 引入依赖
- 限流的规则
- 熔断规则
- yaml 项目配置
- 使用注解 @SentinelResource讲解
- 类的静态方法
sentinel
sentinel介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
重要的核心概念
资源
- 资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
- 只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则 - 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
引入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
</dependencies>
限流的规则
[
{
"resource":"addOrder",
"count":"1",
"grade":"1",
"strategy":"1",
"limitApp":"queryOrder",
"controlBehavior":"0"
}
]
- resource: 定义当前规则绑定限制的资源id 名称
- count: 限流的阈值,grade=1 表示qps上限,grade=0 表示并发上限
- grade: 1 qps类型的限流 0 并发类型限流
- strategy: 限流策略.以哪种方案和逻辑来限流 0直接 1关联 2链路
- limitApp: 流控针对的调用来源,默认default不区分调用来源,配合strategy=1的是后和2的时候使用.
- controlBehavior: 限流效果(0直接拒绝,1Warm up,2排队)
- strategy:
- 0 直接限制,针对当前定义资源,限制访问
- 1 关联,和limitApp有关系,如果当前资源流量,超过限流规则,限制limitApp定义的资源.
- 2 链路 决定限制流量的时候,先判断一下链路的入口,和limitApp有关,表示入口的资源
熔断规则
[
{
"resource": "serviceHi",
"count": 1,
"grade": 0,
"timeWindow": 10,
"minRequestAmount": 1,
"slowRatioThreshold": 0.5,
"statIntervalMs": 10000
}
]
- count: 熔断触发的阈值(不再调用这个资源,而是访问降级策略),如果grade=0 count表示慢调用临界RT(响应时间单位毫秒),超过这个数字,就记录一次慢调用.grade是1,count值应该是>0小于1的小数,表示异常比例,grade=2 count配置整数,表示异常出现的次数
- slowRatioThreshold: 慢调用比例,在grade=0时生效.当满足count记录成慢调用时,达到这个阈值,触发熔断.
- minRequestAmount: 最少统计的请求数量.没达到最少数量,不会触发熔断
- statIntervalMs: 统计时长,在同一个统计时长之内的数据,才能触发熔断.单位毫秒数.
- timeWindow: 如果触发熔断,持续时间,单位秒
- grade: 熔断类型 0 默认值 慢调用比例 1 异常比例 2异常数
当前熔断规则定义:
在10秒钟之内,最少达到1次请求前提下,超过1毫秒的资源处理时间记录为慢调用,如果所有调用请求的慢调用比例达到50%,则资源会熔断,熔断持续时间10秒,10秒后,断路器半开,尝试访问资源,再次计算熔断规则.
- 熔断规则中的异常数.
[
{
"resource": "serviceHi",
"count": 1,
"grade": 2,
"timeWindow": 10,
"minRequestAmount": 1,
"slowRatioThreshold": 0.5,
"statIntervalMs": 10000
}
]
表示内容:
10秒内统计异常数的熔断策略,如果最小请求达到1,并且异常数超过1,进入熔断持续时间10秒.
yaml 项目配置
spring:
cloud:
sentinel:
datasource:
#定义一个数据源的名称
key1:
nacos:
#数据源具体属性 nacos address namespace group-id 文件名称
server-addr: localhost:8848
data-id: flowRules.json
data-type: json
#namespace: f033ea8e-15ca-4f37-b112-127edc03de9e
#每一个数据源的规则类型必须配置
rule-type: flow
#如果sentinel版本高于1.7 必须配置nacos用户名密码
username: nacos
password: nacos
key2:
nacos:
#数据源具体属性 nacos address namespace group-id 文件名称
server-addr: localhost:8848
data-id: degradeRules.json
data-type: json
#namespace: f033ea8e-15ca-4f37-b112-127edc03de9e
#每一个数据源的规则类型必须配置
rule-type: degrade
#如果sentinel版本高于1.7 必须配置nacos用户名密码
username: nacos
password: nacos
使用注解 @SentinelResource讲解
@Service
public class HelloService {
//定义一个方法为sentinel资源使用的注解
//value 定义资源名称
//blockhandler 会在本类中,寻找一个同名的方法,做降级的处理 要求
//方法参数和方法返回值要和当前目标方法一致,并且要求添加一个异常对象的参数
//fallback
public String aaa(String name,BlockException e){
//异常 BlockException 有可能是所有不同规则对应的异常类型
//DegradeException
return "sorry,sayHi方法熔断了,"+name;
}
public String bbb(String name,Throwable e){
return "sorry,sayHi出现了异常,"+name;
}
@SentinelResource(
value = "serviceHi",
blockHandler="aaa",
fallback = "bbb")
public String sayHi(String name){
System.out.println("进入到service的saiHi");
String result="你好啊!"+name;
int a=1/0;
return result;
}
}
类的静态方法
- 为了减少业务代码类中,降级处理逻辑的代码繁杂,提供了简化,静态方法提取
- sentinel允许我们将降级逻辑的代码方法,放到指定的类中,提供静态方法调用.节省本类代码,看起来更整洁.
- 限流目的: 根据预估/压测的数据 实现并发或者qps设置,保护服务器
- 熔断目的: 在保证主要业务功能成功实现前提下,附属,不重要的业务,可以做降级处理,避免他们问题影响主要业务功能
/**
远程调用时,和cart购物车有关的方法
单独封装一个bean对象
*/
@Component
@Slf4j
public class DubboCartService {
@DubboReference
private ICartService cartService;
/**
* 熔断降级的资源方法
* @param orderAddDTO
*/
@SentinelResource(
value="serviceHi",
blockHandler ="aaa" ,
fallback = "bbb")
public void HelloServiceBlockHanlder(OrderAddDTO orderAddDTO){
cartService.deleteUserCart(orderAddDTO.getUserId(), orderAddDTO.getCommodityCode());
}
public void aaa(OrderAddDTO orderAddDTO, BlockException e){
log.error("熔断规则生效,断路器打开状态,orderAddDTO:{},异常信息e:{}",orderAddDTO,e.getMessage());
}
public void bbb(OrderAddDTO orderAddDTO,Throwable e){
log.error("业务调用异常,orderAddDTO:{},异常信息e:{}",orderAddDTO,e.getMessage());
}
}