Spring-Clould-Alibaba-sentinel控制台
什么是Sentinel
Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。
使用sentinel
- 下载sentinel控制台服务器 下载地址 链接
- 使用控制台 在jar目录当中打开控制台,输入java -jar sentinel-dashboard-1.7.0.jar 例:指定端口为8088 并且监控sentinel本身
java -Dserver.port=8088 -Dcsp.sentinel.dashboard.server=localhost:8088 -jar sentinel-dashboard-1.7.0.jar
在浏览器当中输入localhost:8088
用户名和密码为sentinel
- 添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
- 添加配置
sentinel:
transport:
dashboard: localhost:8088
启动服务访问 :http://localhost:8000/getGoodsWithID/1
查看控制台
sentinel功能介绍
资源名称,访问的路径,唯一名称** 针对来源:
- 可以针对调用者进行限流
- 假设两个微服务a和b调用,可以对a和b单独的设置限流规则
- default为不区别来源
阈值类型:
- QPS 当调用api的QPS达到阈值时,就去做限流
- 线程数
- 流控(限流) 当调用api的线程数达到一定的域值时就去做限流
设置阈值 一秒种超过一次时, 就会触发限流
流控模式:直接
流控模式:关联
当联的资源达到域值时, 限流自己 查询接口调用过快, 如果影响修改接口,或者修改接口影响查询接口, 根据业务需求,来进行关联限流
示例:
- 在控制台关联访问路径
- 在代码编写方法
@RequestMapping("/test")
public void test(){
System.out.println("test-------");
}
public static void main(String[] args) throws InterruptedException {
for (int i=0;i<1000;i ){
RestTemplate restTemplate = new RestTemplate();
restTemplate.getForObject("http://localhost:8000/test",Object.class);
Thread.sleep(500);
}
}
- 启动main方法 执行test方法,getGoods因为设置了关联,就会被限流
- 链路:指定资源从入口资源进来的流量,如果达到阈值,就开启限流
流控效果
- 快速失败:直接失败,抛出异常信息
- Warm Up:
根据codeFactor从设置的阈值除以codeFactor,经过预热时长,才到达设置的QPS阈值 假设设置的阈值为90 那么就会90/3(默认) 30 作为最初的阈值 ,预热指定的时长 才去达到90的值限流
- 排队等待
匀速排队,让请求以均匀的速度通过,阈值类型必须设置成QPS,否则无效 超过了定义的时长, 就会抛出异常
代码配置
- 引入依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.0</version>
</dependency>
- 定义资源名称
private static final String GETGOODS_KEY = "getMyGoods";
- 定义限流规则
private static final String GETGOODS_KEY = "getMyGoods";
@RequestMapping("/initFlowRules")
public void initFlowRules(){
List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule();
//设置资源名称
rule.setResource(GETGOODS_KEY);
//设置针对来源
rule.setLimitApp("default");
//设置阈值类型
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
// 设置阈值
rule.setCount(1);
rules.add(rule);
FlowRuleManager.loadRules(rules);
}
- 应用到被限流的接口上
@RequestMapping("/getMyGoods")
public String getMyGoods(){
try (Entry entry = SphU.entry(GETGOODS_KEY)) {
// 被保护的逻辑
return "getMyGoods";
} catch (BlockException ex) {
// 处理被流控的逻辑
return "被限流了";
}
}
启动运行 首先执行 initFlowRules 方法开启限流 http://localhost:8000/initFlowRules
然后执行http://localhost:8000/getMyGoods
当刷新次数超过一秒一次的时候就会被限流
但是每次启动都需要先访问开启initFlowRules方法,所以要设置服务启动时开启限流
- 自动执行流控代码 使用springboot自带的ApplicationRunner接口 使用方式,实现ApplicationRunner接口,在run方法当中执行流控代码
- 使用注解改进代码
- Sentinel 支持通过 @SentinelResource 注解定义资源并配置 blockHandler
- 和 fallback 函数来进行限流之后的处理
- blockHandler 函数会在原方法被限流/降级/系统保护的时候调用
- fallback 函数会针对所有类型的异常
private static final String GET_GOODS_KEY = "getMyGoods";
@SentinelResource(value = GET_GOODS_KEY,blockHandler = "blockHandlerMethod")
@RequestMapping("/getMyGoods")
public String getMyGoods(){
return "getMyGoods";
}
public String blockHandlerMethod(BlockException e){
e.printStackTrace();
return "被限流了---";
}
降级
降级策略: RT:
- 平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,
- 对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位)
- 那么在接下的时间窗口之内,对这个方法的调用都会自动地熔断
异常比例:
- 当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后
- 资源进入降级状态
异常次数:
- 当资源近 1 分钟的异常数目超过阈值之后会进行熔断。
- 注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
热点规则
指定索引参数,如果在时间窗口内超过了指定的阈值,就会触发熔断
参数例外项 可以对指定的参数再进行设置限流 参数级别 对指定的参数限流,甚至对指定参数的值进行限流 注意事项 : 参数必须是基本数据类型或String类型
系统规则
- 和其他的规则不太一样,它是针对应用来设的
- 前面设置的都是争对某一个资源。某一个方法来设置的 阈值类型
- load load是负载,只有在linux机器上才会生效。根据当前系统的负载来决定是不是触发保护。
- RT 这个应用上所有的流量的平均的响应时间,所有服务的平均响应时间超过一个值,那么我就停止接收新的请求,
- 线程数 所有服务访问的线程数加起来
- 入口qps 所有服务的qps加起来达到一个值
- cpu使用率 cpu的使用率超过一个百分比
发生以上这些情况的时候把你整个应用给你断掉。所有服务都不提供了
授权规则
使用授权时要先指定来源,对指定来源的内容进行限流
指定来源方式 新建配置类
代码语言:javascript复制@Component
public class RequestOrigin implements RequestOriginParser {
@Override
public String parseOrigin(HttpServletRequest httpServletRequest) {
//从请求参数中获取origin的参数并返回
String origin = httpServletRequest.getParameter("origin");
//如果获取不到origin 就抛出异常
if (StringUtils.isBlank(origin)){
throw new IllegalArgumentException("必须指定origin");
}
//有参数就返回
return origin;
}
}
指定降级 .设置为黑名单,我这里截图没截好
sentinel整合Feign
- 开启feign与Sentinel集成
feign:
sentinel:
enabled: true
- 创建一个类实现服务GoodsFeignClient接口
@Component
public class GoodsFeignClientFalback implements GoodsFeignClient {
@Override
public Object getGoods() {
return ResponseResult.error("GoodsFeignFallback服务器正在维护,请稍后重试--");
}
@Override
public ResponseResult getgoodsWithID(Integer id) {
return ResponseResult.error("GoodsFeignFallback服务器正在维护,请稍后重试--");
}
@Override
public ResponseResult getgoodsObj(Goods goods) {
return ResponseResult.error("GoodsFeignFallback服务器正在维护,请稍后重试--");
}
}
- 在GoodsFeignClient接口
FeignClient(name = "goods-provide",fallback = GoodsFeignClientFalback.class)
正常访问
设置流控
刷新多次
规则持久化
使用Nacos配置中心实现规则持久化
- 在nacos配置中心当中添加配置josn规则
- 添加依赖
<!--添加此依赖,项目一启动时, 就去到nacos当中读取配置中心-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.0</version>
</dependency>
- 在配置文件当中添加sentinel读取nacos地址
eager: true
datasource:
ds:
nacos:
server-addr: localhost:8849
group-id: DEFAULT_GROUP
rule-type: flow
data-id: getGoods
data-type: json
启动 读取nacos的流控规则
使用AHAS实现规则持久化
- https://help.aliyun.com/document_detail/90323.html
选择公网
勾选java、sdk、Springboot
- 添加依赖
- 去除sentinel的部分依赖 避免冲突
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<exclusions>
<exclusion>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
</exclusion>
</exclusions>
</dependency>
访问一次服务后 看AHAS控制台
和本地的sintinel一样的操作