微服务-sentinel-基本案例,持久化

sentinel

功能

  • 限流 限流文档
  1. 直接拒绝:触发阀值直接抛弃。
  2. 冷启动:在一段时间内针对突发流量缓慢增长处理数量。
    3)匀速器:请求以均匀的速度通过。
  • 降级降级文档
    1)RT 统计时间内,大于预设请求数量,且慢请求大于这个预设比例,则熔断拒绝一段时间。
    2)异常比例,统计时间内,请求总数大于预设请求数,且异常比例大于预设比例,则熔断拒绝一段时间。
    3)异常数,统计时间内,请求总数大于预设请求数量,且异常大于预设数值,则拒绝熔断一段时间。
手动限流案例Demo
  • 根据线程活跃数量进行限流
/*** 根据并发数量进行限流*/
public class Flow_1_Thread_Demo {/** 资源 methodA 所有业务逻辑处理完成的数量 **/private static AtomicInteger pass = new AtomicInteger();/** 资源 methodA 被拒绝的数量 **/private static AtomicInteger block = new AtomicInteger();/** 资源 methodA 接收到请求的总数量 **/private static AtomicInteger total = new AtomicInteger();/** 资源 methodA 真正开始干活时就开始计数,表示 methodA 的任务活跃数 **/private static AtomicInteger activeThread = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 100;/** 资源 methodA 总共被发起调用的持续时间 **/private static int seconds = 15;/** 资源 methodB 处理业务时需要消耗的时间,单位:毫秒 **/private static volatile int methodBRunningTime = 2000;/*** 并发数限流* 当并发数大于 5 时则进行阻断* 反正一直保持最大活跃任务数为 5*/private static void initFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule = new FlowRule();// 设置资源名称为:methodArule.setResource("methodA");// 设置限流类型:并发数限流rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);// 设置并发数限流,对应的限制数值rule.setCount(5);// 设置需要限制哪些应用,如果没有想好需要限制谁的话,那么采用 default 方式rule.setLimitApp("default");// 将设置好的规则,添加至列表中,并且加载到限流管理器中rules.add(rule);FlowRuleManager.loadRules(rules);System.out.println("Flow_1_Thread rule loaded: " + rules);}public static void main(String[] args) throws Exception {System.out.println("MethodA will call methodB. After running for a while, methodB becomes fast, "+ "which make methodA also become fast ");// 开启一个线程打印统计信息tick();// 设置规则initFlowRule();// 启动现场 不停的发送请求for (int i = 0; i < threadCount; i++) {Thread entryThread = new Thread(new ThreadRunTask());entryThread.setName("working thread");entryThread.start();}}private static void tick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();}/*** 打印统计信息 每秒钟输出*/static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.print("【秒】倒计时: " + seconds + ", ");System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date()))+ ", 每秒总请求量:" + oneSecondTotal+ ", 每秒完成量:" + oneSecondPass+ ", 每秒拒绝量:" + oneSecondBlock+ ", 每秒活跃量:" + activeThread.get());System.out.println();if (seconds-- <= 0) {stop = true;}// 倒数5秒的时候提高MethodB 方法的效率if (seconds == 5) {System.out.println("method B 原来执行需要花费 2000 毫秒,改造后只需要花费 20 毫秒,系统即将能处理更多的请求。\n");methodBRunningTime = 20;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total:" + total.get() + ", pass:" + pass.get()+ ", block:" + block.get());System.exit(0);}}static class ThreadRunTask implements Runnable {@Overridepublic void run() {while (true) {Entry methodA = null;try {TimeUnit.MILLISECONDS.sleep(5);// 抢占资源AmethodA = SphU.entry("methodA");activeThread.incrementAndGet();// 抢占资源BEntry methodB = SphU.entry("methodB");TimeUnit.MILLISECONDS.sleep(methodBRunningTime);methodB.exit();pass.addAndGet(1);} catch (BlockException e1) {// 阻塞的数量block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {// 请求总数量total.incrementAndGet();if (methodA != null) {methodA.exit();// 活跃数量减activeThread.decrementAndGet();}}}}}
}
  • 根据QPS进行限流
/*** 根据QPS进行限流*/
public class Flow_2_Qps_Demo {private static final String KEY = "methodA";/** 资源 methodA 所有业务逻辑处理完成的数量 **/private static AtomicInteger pass = new AtomicInteger();/** 资源 methodA 被拒绝的数量 **/private static AtomicInteger block = new AtomicInteger();/** 资源 methodA 接收到请求的总数量 **/private static AtomicInteger total = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 32;/** 资源 methodA 总共被发起调用的持续时间 **/private static int seconds = 15;private static void initFlowQpsRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();// 设置资源名称为:methodArule1.setResource(KEY);// 设置限流类型:QPS 限流rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置 QPS 限流,对应的限制数值rule1.setCount(5);// 设置 QPS 限流数值满后的应对策略:直接拒绝(该策略为默认策略,可以从 setControlBehavior 方法跟踪进去看)// public static final int CONTROL_BEHAVIOR_DEFAULT = 0;// public static final int CONTROL_BEHAVIOR_WARM_UP = 1;// public static final int CONTROL_BEHAVIOR_RATE_LIMITER = 2;// public static final int CONTROL_BEHAVIOR_WARM_UP_RATE_LIMITER = 3;// rule1.setControlBehavior()// 设置需要限制哪些应用,如果没有想好需要限制谁的话,那么采用 default 方式rule1.setLimitApp("default");// 将设置好的规则,添加至列表中,并且加载到限流管理器中rules.add(rule1);FlowRuleManager.loadRules(rules);System.out.println("Flow_2_Qps rule loaded: " + rules);}public static void main(String[] args) throws Exception {initFlowQpsRule();tick();// first make the system run on a very low conditionsimulateTraffic();System.out.println("===== begin to do flow control");System.out.println("only 5 requests per second can pass");}private static void simulateTraffic() {for (int i = 0; i < threadCount; i++) {Thread t = new Thread(new RunTask());t.setName("simulate-traffic-Task");t.start();}}private static void tick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.print("【秒】倒计时: " + seconds + ", ");System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date()))+ ", 每秒总请求量:" + oneSecondTotal+ ", 每秒完成量:" + oneSecondPass+ ", 每秒拒绝量:" + oneSecondBlock);System.out.println();if (seconds-- <= 0) {stop = true;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total:" + total.get() + ", pass:" + pass.get()+ ", block:" + block.get());System.exit(0);}}static class RunTask implements Runnable {@Overridepublic void run() {while (!stop) {Entry entry = null;try {entry = SphU.entry(KEY);// token acquired, means passpass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}Random random2 = new Random();try {TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));} catch (InterruptedException e) {// ignore}}}}
}
  • 冷启动
    也就是在一定的时间内慢慢可以达到我们处理请求的峰值。
public class Flow_3_WarmUp_Demo {private static final String KEY = "methodA";/** 资源 methodA 所有业务逻辑处理完成的数量 **/private static AtomicInteger pass = new AtomicInteger();/** 资源 methodA 被拒绝的数量 **/private static AtomicInteger block = new AtomicInteger();/** 资源 methodA 接收到请求的总数量 **/private static AtomicInteger total = new AtomicInteger();private static volatile boolean stop = false;private static final int threadCount = 100;/** 资源 methodA 总共被发起调用的持续时间 **/private static int seconds = 16;private static void initFlowRule() {List<FlowRule> rules = new ArrayList<FlowRule>();FlowRule rule1 = new FlowRule();// 设置资源名称为:methodArule1.setResource(KEY);// 设置限流类型:QPS 限流rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);// 设置 QPS 限流,对应的限制数值rule1.setCount(20);// 设置 QPS 限流数值满后的应对策略:冷启动,即让通过的流量缓慢增加,直到增加到限制数值上限rule1.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);// 既然设置了冷启动缓慢增长,那么这个缓慢增长到限制数值上限的时间为:10 秒rule1.setWarmUpPeriodSec(10);// 设置需要限制哪些应用,如果没有想好需要限制谁的话,那么采用 default 方式rule1.setLimitApp("default");// 将设置好的规则,添加至列表中,并且加载到限流管理器中rules.add(rule1);FlowRuleManager.loadRules(rules);System.out.println("Flow_3_WarmUp rule loaded: " + rules);}public static void main(String[] args) throws Exception {initFlowRule();// trigger Sentinel internal initEntry entry = null;try {entry = SphU.entry(KEY);} catch (Exception e) {} finally {if (entry != null) {entry.exit();}}Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-task");timer.start();//first make the system run on a very low conditionfor (int i = 0; i < 3; i++) {// WarmUpTask 控制住了调用资源 methodA 的频率,让系统处于一个低水平调用状态Thread t = new Thread(new WarmUpTask());t.setName("sentinel-warmup-task");t.start();}Thread.sleep(5000);/** Start more thread to simulate more qps. Since we use {@link RuleConstant.CONTROL_BEHAVIOR_WARM_UP} as* {@link FlowRule#controlBehavior}, real passed qps will increase to {@link FlowRule#count} in* {@link FlowRule#warmUpPeriodSec} seconds.*/for (int i = 0; i < threadCount; i++) {// RunTask 稍微加大了调用资源 methodA 的频率,让系统处于一个相对原来处于一个较高水平调用状态Thread t = new Thread(new RunTask());t.setName("sentinel-run-task");t.start();}}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("begin to statistic!!!");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;while (!stop) {try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {}long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.print("【秒】倒计时: " + seconds + ", ");System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date()))+ ", 每秒总请求量:" + oneSecondTotal+ ", 每秒完成量:" + oneSecondPass+ ", 每秒拒绝量:" + oneSecondBlock);System.out.println();if (seconds-- <= 0) {stop = true;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total:" + total.get() + ", pass:" + pass.get()+ ", block:" + block.get());System.exit(0);}}static class WarmUpTask implements Runnable {@Overridepublic void run() {while (!stop) {Entry entry = null;try {entry = SphU.entry(KEY);// token acquired, means passpass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}Random random2 = new Random();try {TimeUnit.MILLISECONDS.sleep(random2.nextInt(2000));} catch (InterruptedException e) {// ignore}}}}static class RunTask implements Runnable {@Overridepublic void run() {while (!stop) {Entry entry = null;try {entry = SphU.entry(KEY);pass.addAndGet(1);} catch (BlockException e1) {block.incrementAndGet();} catch (Exception e2) {// biz exception} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}Random random2 = new Random();try {TimeUnit.MILLISECONDS.sleep(random2.nextInt(50));} catch (InterruptedException e) {// ignore}}}}
}
手动降级案例Demo
  • 根据响应时间来限流
    也就是统计慢请求超过一定的比例以后,则在我们设置的时间内停止干活儿,知道下一次请求处理小于我们设置的慢请求的时间,继续干活。
public class Degrade_1_RT_Demo {private static final String KEY = "methodA";private static volatile boolean stop = false;private static int seconds = 120;/** 资源 methodA 接收到请求的总数量 **/private static AtomicInteger total = new AtomicInteger();/** 资源 methodA 被拒绝的数量 **/private static AtomicInteger block = new AtomicInteger();/** 资源 methodA 真正开始干活时就开始计数,表示 methodA 的任务活跃数 **/private static AtomicInteger activeThread = new AtomicInteger();private static void initDegradeRule() {List<DegradeRule> rules = new ArrayList<>();DegradeRule rule = new DegradeRule();// 设置资源名称为:methodArule.setResource(KEY);// 设置熔断策略:慢调用比例策略rule.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType());// 既然策略为慢调用比例,那么设置当请求的响应时间大于 50 毫秒时,则统计为慢调用rule.setCount(50);// 触发熔断条件 1:最小请求数,若【统计时长】内请求数小于该值时,即使【异常比率】超出 count 阈值也不会熔断rule.setMinRequestAmount(10);// 触发熔断条件 2:所谓的【统计时长】是多少,即到底在多少时间内进行统计计数rule.setStatIntervalMs(8000);// 触发熔断条件 3:所谓的【异常比率】其实就是一个 0 到 1 之间的数值,异常数 = minRequestAmount * slowRatioThresholdrule.setSlowRatioThreshold(0.2);// 当熔断触发后,熔断时长(10 秒)内请求会自动被熔断// 经过熔断时长后,若接下来的一个请求响应时间小于 RT 则结束熔断rule.setTimeWindow(10);// 将设置好的规则,添加至列表中,并且加载到熔断降级管理器中rules.add(rule);DegradeRuleManager.loadRules(rules);System.out.println("Degrade rule loaded: " + rules);}public static void main(String[] args) throws Exception {initDegradeRule();registerStateChangeObserver();startTick();int concurrency = 8;for (int i = 0; i < concurrency; i++) {Thread entryThread = new Thread(new DegradeRTTask());entryThread.setName("sentinel-simulate-traffic-task-" + i);entryThread.start();}}private static void registerStateChangeObserver() {EventObserverRegistry.getInstance().addStateChangeObserver("logging",(prevState, newState, rule, snapshotValue) -> {if (newState == State.OPEN) {System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),TimeUtil.currentTimeMillis(), snapshotValue));} else {System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),TimeUtil.currentTimeMillis()));}});}private static void sleep(int timeMs) {try {TimeUnit.MILLISECONDS.sleep(timeMs);} catch (InterruptedException e) {// ignore}}private static void startTick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-tick-task");timer.start();}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("Begin to run! Go go go!");System.out.println("See corresponding metrics.log for accurate statistic data");long oldTotal = 0;long oldActivePass = 0;long oldBlock = 0;while (!stop) {sleep(1000);long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long currActivePass = activeThread.get();long oneSecondPass = currActivePass - oldActivePass;oldActivePass = currActivePass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;System.out.print("【秒】倒计时: " + seconds + ", ");System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date()))+ ", 每秒总请求量:" + oneSecondTotal+ ", 每秒活跃量:" + oneSecondPass+ ", 每秒拒绝量:" + oneSecondBlock);if (seconds-- <= 0) {stop = true;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total: " + total.get() + ", pass:" + activeThread.get()+ ", block:" + block.get());System.exit(0);}}static class DegradeRTTask implements Runnable {@Overridepublic void run() {while (true) {Entry entry = null;try {entry = SphU.entry(KEY);activeThread.incrementAndGet();// RT: [40ms, 80ms)sleep(ThreadLocalRandom.current().nextInt(40, 80));} catch (BlockException e) {block.incrementAndGet();sleep(ThreadLocalRandom.current().nextInt(5, 10));} finally {total.incrementAndGet();if (entry != null) {entry.exit();}}}}}
}
  • 异常比例
    也就是异常超过我们预设的比例,接下来我们设置的时间内都不干活,知道我们后面成功处理了一个请求接着干活。
public class Degrade_2_ExceptionRatio_Demo {private static final String KEY = "methodA";private static AtomicInteger total = new AtomicInteger();private static AtomicInteger pass = new AtomicInteger();private static AtomicInteger block = new AtomicInteger();private static AtomicInteger bizException = new AtomicInteger();private static volatile boolean stop = false;private static int seconds = 120;private static void initDegradeRule() {List<DegradeRule> rules = new ArrayList<>();DegradeRule rule = new DegradeRule();// 设置资源名称为:methodArule.setResource(KEY);// 设置熔断策略:异常比例策略rule.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType());// 既然策略为异常比例,出现业务异常则统计异常数量,当异常比例大于 50% 时,则触发熔断rule.setCount(0.5d);// 触发熔断条件 1:最小请求数,若【统计时长】内请求数小于该值时,即使【异常比例】超出 count 阈值也不会熔断rule.setMinRequestAmount(10);// 触发熔断条件 2:所谓的【统计时长】是多少,即到底在多少时间内进行统计计数rule.setStatIntervalMs(10000);// 当熔断触发后,熔断时长(10 秒)内请求会自动被熔断// 经过熔断时长后,若接下来的一个请求成功返回,则结束熔断rule.setTimeWindow(10);// 将设置好的规则,添加至列表中,并且加载到熔断降级管理器中rules.add(rule);DegradeRuleManager.loadRules(rules);System.out.println("Degrade rule loaded: " + rules);}public static void main(String[] args) throws Exception {initDegradeRule();registerStateChangeObserver();startTick();final int concurrency = 8;for (int i = 0; i < concurrency; i++) {Thread entryThread = new Thread(new DegradeErrorRatioTask());entryThread.setName("sentinel-simulate-traffic-task-" + i);entryThread.start();}}private static void registerStateChangeObserver() {EventObserverRegistry.getInstance().addStateChangeObserver("logging",(prevState, newState, rule, snapshotValue) -> {if (newState == State.OPEN) {System.err.println(String.format("%s -> OPEN at %d, snapshotValue=%.2f", prevState.name(),TimeUtil.currentTimeMillis(), snapshotValue));} else {System.err.println(String.format("%s -> %s at %d", prevState.name(), newState.name(),TimeUtil.currentTimeMillis()));}});}private static void sleep(int timeMs) {try {TimeUnit.MILLISECONDS.sleep(timeMs);} catch (InterruptedException e) {// ignore}}private static void startTick() {Thread timer = new Thread(new TimerTask());timer.setName("sentinel-timer-tick-task");timer.start();}static class TimerTask implements Runnable {@Overridepublic void run() {long start = System.currentTimeMillis();System.out.println("Begin to run! Go go go!");System.out.println("See corresponding metrics.log for accurate statistic data");long oldTotal = 0;long oldPass = 0;long oldBlock = 0;long oldBizException = 0;while (!stop) {sleep(1000);long globalTotal = total.get();long oneSecondTotal = globalTotal - oldTotal;oldTotal = globalTotal;long globalPass = pass.get();long oneSecondPass = globalPass - oldPass;oldPass = globalPass;long globalBlock = block.get();long oneSecondBlock = globalBlock - oldBlock;oldBlock = globalBlock;long globalBizException = bizException.get();long oneSecondBizException = globalBizException - oldBizException;oldBizException = globalBizException;//                System.out.println(TimeUtil.currentTimeMillis() + ", oneSecondTotal:" + oneSecondTotal
//                    + ", oneSecondPass:" + oneSecondPass
//                    + ", oneSecondBlock:" + oneSecondBlock
//                    + ", oneSecondBizException:" + oneSecondBizException);System.out.print("【秒】倒计时: " + seconds + ", ");System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS").format(new Date()))+ ", 每秒总请求量:" + oneSecondTotal+ ", 每秒完成量:" + oneSecondPass+ ", 每秒拒绝量:" + oneSecondBlock+ ", 每秒业务异常量:" + oneSecondBizException);if (seconds-- <= 0) {stop = true;}}long cost = System.currentTimeMillis() - start;System.out.println("time cost: " + cost + " ms");System.out.println("total: " + total.get() + ", pass:" + pass.get()+ ", block:" + block.get() + ", bizException:" + bizException.get());System.exit(0);}}static class DegradeErrorRatioTask implements Runnable {@Overridepublic void run() {while (true) {Entry entry = null;try {entry = SphU.entry(KEY);sleep(ThreadLocalRandom.current().nextInt(5, 10));pass.addAndGet(1);// Error probability is 45%if (ThreadLocalRandom.current().nextInt(0, 100) > 55) {// biz code raise an exception.throw new RuntimeException("oops");}} catch (BlockException e) {block.addAndGet(1);sleep(ThreadLocalRandom.current().nextInt(5, 10));} catch (Throwable t) {bizException.incrementAndGet();// It's required to record exception here manually.Tracer.traceEntry(t, entry);} finally {total.addAndGet(1);if (entry != null) {entry.exit();}}}}}
}
直接使用框架

在这里插入图片描述

  • Sentinel 控制台
    参考官方文档
    在这里插入图片描述

下载jar以后可以创建一个命令启动文件:startup.cmd

java -Dserver.port=9999 -Dcsp.sentinel.dashboard.server=localhost:9999 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

然后有这样一个控制台:
在这里插入图片描述

  • Sentinel 服务端
    父POM
 <dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${com.alibaba.cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${com.cloud.version}</version><type>pom</type><scope>import</scope></dependency><!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-dubbo --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-dubbo</artifactId><version>${com.dubbo.version}</version></dependency></dependencies></dependencyManagement>

工程POM

<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

接入Nacos

在这里插入图片描述

工程pom

 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-datasource-nacos</artifactId></dependency>
spring:application:name: sentinel-online-flowdeg-consumercloud:nacos:discovery:server-addr: 111.229.199.181:8848sentinel:transport:port: 8719dashboard: 127.0.0.1:9999datasource:r1:nacos:# nacos地址server-addr: 111.229.199.181:8848# nacos中配置文件的data-iddata-id: sentinel-online-flowdeg-consumer# nacos 分组group-id: DEFAULT_GROUPdata-type: json# 规则类型 流控rule-type: flownamespace: 05b6571e-7791-4af9-9522-f8097beac3d7server:port: 9064

nacos 配置

[{"limitApp": "default","resource": "/echo/{string}","grade": 1,"count": 20,"strategy": 0,"refResource": null,"controlBehavior": 0,"warmUpPeriodSec": null,"maxQueueingTimeMs": null,"clusterMode": false,"clusterConfig":{"flowId": null,"thresholdType": 0,"fallbackToLocalWhenFail": true,"strategy": 0,"sampleCount": 10,"windowIntervalMs": 1000,"resourceTimeout": 2000,"resourceTimeoutStrategy": 0,"acquireRefuseStrategy": 0,"clientOfflineTime": 2000},"gmtCreate": "2024-01-05T06:03:30.663+00:00","gmtModified": "2024-01-05T06:03:30.663+00:00"}
]

在这里插入图片描述

Nacos Sentinel持久化

在这里插入图片描述

触发一次 Http 请求调用后,发现进入了 com.alibaba.csp.sentinel.init.InitExecutor#doInit 断点

循环逻辑代码块分析

for (InitFunc initFunc : loader) {RecordLog.info("[InitExecutor] Found init func: " + initFunc.getClass().getCanonicalName());insertSorted(initList, initFunc);
}
for (OrderWrapper w : initList) {w.func.init();RecordLog.info(String.format("[InitExecutor] Executing %s with order %d",w.func.getClass().getCanonicalName(), w.order));
}

寻找到了 com.alibaba.csp.sentinel.transport.command.SimpleHttpCommandCenter#start 的相关收发数据逻辑

关键代码 1:开启服务端层面的线程


socketReference = serverSocket;
executor.submit(new ServerThread(serverSocket));
success = true;
port = serverSocket.getLocalPort();

关键代码 2:从 ServerSocket 的 accept 方法收数据

socket = this.serverSocket.accept();
setSocketSoTimeout(socket);
HttpEventTask eventTask = new HttpEventTask(socket);
bizExecutor.submit(eventTask);

数据源处理核心代码

if (FLOW_RULE_TYPE.equalsIgnoreCase(type)) {List<FlowRule> flowRules = JSONArray.parseArray(data, FlowRule.class);FlowRuleManager.loadRules(flowRules);if (!writeToDataSource(getFlowDataSource(), flowRules)) {result = WRITE_DS_FAILURE_MSG;}return CommandResponse.ofSuccess(result);
}
基于上面的源码分析

我们写下面两个类,来完成限流配置的持久化。

@Configuration
public class NacosLinkSentinelConfig implements InitializingBean {@Overridepublic void afterPropertiesSet() throws Exception {}@PostConstructpublic void init() throws Exception {NacosWritableDataSource ds = new NacosWritableDataSource("sentinel-nacos-persist-consumer-flow.json","DEFAULT_GROUP","ip","05b6571e-7791-4af9-9522-f8097beac3d7");WritableDataSourceRegistry.registerFlowDataSource(ds);}
}
public class NacosWritableDataSource<T> implements WritableDataSource<T> {private String dataId;private String group;private ConfigService configService;public NacosWritableDataSource(String dataId,String group,String serverAddr,String namespace) throws Exception {this.dataId = dataId;this.group = group;Properties properties = new Properties();properties.setProperty(PropertyKeyConst.SERVER_ADDR, serverAddr);properties.setProperty(PropertyKeyConst.NAMESPACE, namespace);properties.setProperty(PropertyKeyConst.USERNAME, "nacos");properties.setProperty(PropertyKeyConst.PASSWORD, "nacos");configService = NacosFactory.createConfigService(properties);}@Overridepublic void write(T t) throws Exception {configService.publishConfig(this.dataId, this.group, JSON.toJSONString(t),  "json");}@Overridepublic void close() throws Exception {}
}

这样我们在界面修改就可以持久化到nacos,这里要注意如果在nacos直接修改,控制台上是不能感知到的。
在这里插入图片描述
下次重启控制台,Nacos被持久化规则也会进行加载:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/325466.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#,简单选择排序算法(Simple Select Sort)的源代码与数据可视化

排序算法是编程的基础。 常见的四种排序算法是&#xff1a;简单选择排序、冒泡排序、插入排序和快速排序。其中的快速排序的优势明显&#xff0c;一般使用递归方式实现&#xff0c;但遇到数据量大的情况则无法适用。实际工程中一般使用“非递归”方式实现。本文搜集发布四种算法…

Java经典框架之Zookeeper

Zookeeper Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. Zookeeper的介绍和安装 2. …

LINUX基础培训之开机启动过程

前言、本章学习目标 掌握系统启动、引导过程 了解grub.conf的参数设置 熟悉系统运行级别 了解加载内核过程 一、LINUX启动引导过程 Linux系统的启动过程并不是大家想象中的那么复杂&#xff0c;其过程可以分为5个阶段&#xff1a; 1.开机自检 服务器主机开机以后&#xf…

c# 学习笔记 - 委托(Delegate)

文章目录 1. 委托1.1 委托概述1.2 委托使用1.3 委托的传播 2. 匿名方法2.1 匿名方法概述2.2 匿名方法 1. 委托 1.1 委托概述 委托简介 委托就是对方法的引用&#xff0c;可以理解为例如整型变量的容器可以存储整形数据&#xff0c;委托就是某种方法的容器&#xff0c;可以用来…

Raft Lab3A

Lab3 需要在 Raft 层上实现一个 fault-tolerant key-value service&#xff0c;满足强一致性&#xff0c;也就是线性一致性 (Linearizable Consistency)。线性一致性保证整个系统看起来好像只有一个副本&#xff0c;其中所有的操作都是原子性的。简单地说&#xff0c;线性一致性…

swing快速入门(三十九)进度对话框

&#x1f381;注释很详细&#xff0c;直接上代码 &#x1f9e7;新增内容 &#x1f9e8;1.模拟耗时操作 &#x1f9e8;2.使用计时器更新进度对话框 &#x1f380;源码&#xff1a; package swing31_40;import javax.swing.*; import java.awt.event.ActionEvent; import java.aw…

【动态规划】【字符串】132.分割回文串 II

作者推荐 【动态规划】【字符串】扰乱字符串 本文涉及的基础知识点 动态规划 字符串 LeetCode132. 分割回文串 II 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1&#xff1a; 输入&#x…

alpha测试和beta测试Gamma测试的区别是什么?

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;软件测试面试题分享&#xff1a; 1000道软件测试面试题及答案&#x1f4e2;软件测试实战项目分享&#xff1a; 纯接口项目-完…

CSS基础笔记-01CSS概述

文章目录 前言CSS是什么CSS的作用CSS语法添加CSS的方法 前言 CSS是什么&#xff1f;有什么作用&#xff1f;怎么编写CSS&#xff1f;怎样添加CSS&#xff1f;本文对CSS的四个方面作了学习并形成学习笔记。 CSS是什么 CSS &#xff08;Cascading Style Sheets&#xff0c;层叠…

开源网络安全工具

开源工具代表了技术领域的一股动态力量&#xff0c;体现了创新、协作和可访问性。这些工具以透明度和社区驱动的原则开发&#xff0c;允许用户根据自己的独特需求仔细检查、修改和调整解决方案。 在网络安全领域&#xff0c;开源工具是无价的资产&#xff0c;使组织能够增强防…

kubectl常用命令(全局篇)

格式 -o [cmd] -o json|yaml|wide 如&#xff1a;输出json格式 kubectl get ns ingress-nginx -o json 获取基本信息get #查看集群基本信息 kubectl get cs|pods|nodes|ns|svc|rc|deployments kubectl get cs kubectl get pods kubectl get nodes kubectl get ns kubectl g…

P1025 [NOIP2001 提高组] 数的划分———C++(动态规划、DFS)

目录 [NOIP2001 提高组] 数的划分题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示 动态规划的解题思路Code运行结果DFSCode运行结果 [NOIP2001 提高组] 数的划分 题目描述 将整数 n n n 分成 k k k 份&#xff0c;且每份不能为空&#xff0c;任意两个方案不相…