# 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