# kim-sentinel
**Repository Path**: java-233/kim-sentinel
## Basic Information
- **Project Name**: kim-sentinel
- **Description**: 使用sentinel集成springcloud项目
①使用流控规则(qps限制)
②使用熔断降级
a.慢调用比例 b.异常比例 c.异常数
③sentinel监控数据持久化到mysql
④sentinel规则持久化到redis
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 5
- **Created**: 2022-01-28
- **Last Updated**: 2022-01-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
启动sentinel
启动sentinel-dashboard项目,已经进行改造
Sentinel与SpringCloud整合
1)、创建SpringBoot项目,引入spring-cloud-starter-alibaba-sentinel依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
2.2.3.RELEASE
A.sentinel监控持久化到mysql(相关代码参考sentinel-dashboard服务)
①创建数据库sentinel
②执行sentinel.sql文件
③修改配置文件sentinel-dashboard下的application.properties文件至实际使用即可
sentinel-dashboard已经改造完成至mysql,详细改造过程不再赘述
添加qps配置文件
package com.b.server.config;
import com.alibaba.csp.sentinel.annotation.aspectj.SentinelResourceAspect;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 实现流控规则qps
*/
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
B.sentinel规则持久化到redis(相关代码参考Kim-b 和 sentinel-dashboard服务)
①当前项目使用redis dabatase为1,可根据实际情况进行修改
修改的文件为 kim -b 和 sentinel-dashboard的配置文件
sentinel-dashboard已经改造完成至redis,详细改造过程不再赘述
应用接入
添加redis配置文件
package com.b.server.config;
import com.alibaba.csp.sentinel.config.SentinelConfig;
import com.alibaba.csp.sentinel.datasource.Converter;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.redis.RedisDataSource;
import com.alibaba.csp.sentinel.datasource.redis.config.RedisConnectionConfig;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @author zhuhongqiang3
* @package: com.example.sentinel_demo.config
* @title: RedisDataSourceConfig
* @projectName: sentinel_demo
* @description: //TODO
* @date: 2020-05-18 10:36
* @version: V1.0
* @retrun com.example.sentinel_demo.config.sentinel_demo
*/
@Component
public class RedisDataSourceConfig implements ApplicationRunner {
private static final Logger log = LoggerFactory.getLogger(RedisDataSourceConfig.class);
@Value("${spring.redis.host}")
public String redisHost;
@Value("${spring.redis.port}")
public int redisPort;
@Value("${spring.redis.password}")
public String redisPass;
//限流规则key前缀
public final String RULE_FLOW = "sentinel_rule_flow_";
public final String RULE_FLOW_CHANNEL = "sentinel_rule_flow_channel";
//降级规则key前缀
public final String RULE_DEGRADE = "sentinel_rule_degrade_";
public final String RULE_DEGRADE_CHANNEL = "sentinel_rule_degrade_channel";
//系统规则key前缀
public final String RULE_SYSTEM = "sentinel_rule_system_";
public final String RULE_SYSTEM_CHANNEL = "sentinel_rule_system_channel";
/**
* ApplicationRunner
* 该接口的方法会在服务启动之后被立即执行
* 主要用来做一些初始化的工作
* 但是该方法的运行是在SpringApplication.run(…) 执行完毕之前执行
*/
@Override
public void run(ApplicationArguments args) {
log.info(">>>>>>>>>执行sentinel规则初始化 start。。。");
RedisConnectionConfig config = RedisConnectionConfig.builder().withHost(redisHost).withPort(redisPort).withPassword(redisPass).build();
Converter> parser = source -> JSON.parseObject(source, new TypeReference>() {
});
String ruleAppName = RULE_FLOW + SentinelConfig.getAppName();
log.info("ruleAppName>>>" + ruleAppName);
ReadableDataSource> redisDataSourceFlow = new RedisDataSource<>(config, ruleAppName, RULE_FLOW_CHANNEL, parser);
FlowRuleManager.register2Property(redisDataSourceFlow.getProperty());
Converter> parserDegrade = source -> JSON.parseObject(source, new TypeReference>() {
});
ReadableDataSource> redisDataSourceDegrade = new RedisDataSource<>(config, RULE_DEGRADE + SentinelConfig.getAppName(), RULE_DEGRADE_CHANNEL, parserDegrade);
DegradeRuleManager.register2Property(redisDataSourceDegrade.getProperty());
Converter> parserSystem = source -> JSON.parseObject(source, new TypeReference>() {
});
ReadableDataSource> redisDataSourceSystem = new RedisDataSource<>(config, RULE_SYSTEM + SentinelConfig.getAppName(), RULE_SYSTEM_CHANNEL, parserSystem);
SystemRuleManager.register2Property(redisDataSourceSystem.getProperty());
log.info(">>>>>>>>>执行sentinel规则初始化 end。。。");
}
}
配置文件关键代码
###数据库配置
spring:
cloud:
sentinel:
transport:
dashboard: 127.0.0.1:9090 #对应自己的sentinel控制台端口
port: 8719 #您的项目和sentinel交互使用的端口
redis:
host: 127.0.0.1
port: 6379
password: 123456
database: 1
流控规则
1)、创建Controller,实现流控规则
/**
* 测试sentinel 流控规则
* 首页 -> 服务名 -> 流控规则
* @return
*/
@PostMapping("/flowControl")
//定义资源 value:设置资源的名称 blockHandler:设置限流或降级的处理函数
@SentinelResource(value = "flowControl", blockHandler = "exceptionHandler")
public String flowControl() {
log.info("b服务正在被调用 {} ", i++);
return "ok";
}
//被限流的处理函数
public String exceptionHandler(BlockException ex) {
ex.printStackTrace();
return "系统繁忙,请稍候";
}
2)、在控制台中设置限流规则
①
进入sentinel控制台:localhost:9090
账号密码默认 sentinel
②
找到首页
找到服务名(若服务名不存在,使用接口多点击几次即会出现)
点击流控规则
新增即可
测试接口
localhost:31001/a/flowControl
熔断降级
1) 慢调用比例
平均响应时间 (DEGRADE_GRADE_RT):当 1s 内持续进入 5 个请求,对应时刻的平均响应时间(秒级)均超过阈值(count,以 ms 为单位),那么在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地熔断(抛出 DegradeException)。注意 Sentinel 默认统计的 RT 上限是 4900 ms,超出此阈值的都会算作 4900 ms,若需要变更此上限可以通过启动配置项 -Dcsp.sentinel.statistic.max.rt=xxx 来配置。
慢调用:指耗时大于阈值RT的请求称为慢调用,阈值RT由用户设置
最小请求数:允许通过的最小请求数量,在最小请求数量内不发生熔断,由用户设置
属性 说明
最大RT 需要设置的阈值,超过该值则为慢应用
比例阈值 慢调用占所有的调用的比率,范围:[0~1]
熔断时长 在这段时间内发生熔断、拒绝所有请求
最小请求数 即允许通过的最小请求数,在该数量内不发生熔断
执行逻辑
熔断(OPEN):请求数大于最小请求数并且慢调用的比率大于比例阈值则发生熔断,熔断时长为用户自定义设置。
探测(HALFOPEN):当熔断过了定义的熔断时长,状态由熔断(OPEN)变为探测(HALFOPEN)。
如果接下来的一个请求小于最大RT,说明慢调用已经恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
如果接下来的一个请求大于最大RT,说明慢调用未恢复,继续熔断,熔断时长保持一致
测试接口
localhost:31001/a/timeout
2) 异常比例
异常比例 (DEGRADE_GRADE_EXCEPTION_RATIO):当资源的每秒请求量 >= 5,并且每秒异常总数占通过量的比值超过阈值(DegradeRule 中的 count)之后,资源进入降级状态,即在接下的时间窗口(DegradeRule 中的 timeWindow,以 s 为单位)之内,对这个方法的调用都会自动地返回。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
通过计算异常比例与设置阈值对比的一种策略。
属性 说明
异常比例阈值 异常比例=发生异常的请求数÷请求总数取值范围:[0~1]
熔断时长 在这段时间内发生熔断、拒绝所有请求
最小请求数 即允许通过的最小请求数,在该数量内不发生熔断
执行逻辑
熔断(OPEN):当请求数大于最小请求并且异常比例大于设置的阈值时触发熔断,熔断时长由用户设置。
探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致
测试接口(使用Jmeter)
localhost:31001/a/abnormalProportion
3) 异常数
异常数 (DEGRADE_GRADE_EXCEPTION_COUNT):当资源近 1 分钟的异常数目超过阈值之后会进行熔断。注意由于统计时间窗口是分钟级别的,若 timeWindow 小于 60s,则结束熔断状态后仍可能再进入熔断状态。
通过计算发生异常的请求数与设置阈值对比的一种策略。
属性 说明
异常数 请求发生异常的数量
熔断时长 在这段时间内发生熔断、拒绝所有请求
最小请求数 即允许通过的最小请求数,在该数量内不发生熔断
执行逻辑
熔断(OPEN):当请求数大于最小请求并且异常数量大于设置的阈值时触发熔断,熔断时长由用户设置。探测(HALFOPEN):当超过熔断时长时,由熔断(OPEN)转为探测(HALFOPEN)
如果接下来的一个请求未发生错误,说明应用恢复,结束熔断,状态由探测(HALF_OPEN)变更为关闭(CLOSED)
如果接下来的一个请求继续发生错误,说明应用未恢复,继续熔断,熔断时长保持一致
测试接口(使用Jmeter)
localhost:31001/a/abnormalNumber