微服务-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.mzph.cn/news/600687.shtml

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

相关文章

MySQL数据库的查询操作

MySQL单表查询 字段解析字段名字段类型雇员编号idint雇员姓名namevarchar(30)雇员性别sexenum雇用时期hire_datedate雇员职位postvarchar(50)职位描述job_descriptionvarchar(100)雇员薪水salarydouble(15,2)办公室officeint部门编号dep_idint #创表 CREATE TABLE company.em…

架构(1)

目录 1.如何理解架构的演进&#xff1f; 2.如何理解架构的服务化趋势&#xff1f; 3.架构中有哪些技术点&#xff1f; 4.谈谈架构中的缓存应用&#xff1f; 5.在开发中缓存具体如何实现&#xff1f; 1.如何理解架构的演进&#xff1f; 初始阶段的网站架构应用服务和数据服…

tcl 基础

exec catch file mkdir

【QT】QStandardItemModel类的应用介绍

目录 1 概述 2 常用方法 3 QStandardItemModel的使用 3.1 界面设计与主窗口类定义 3.2 系统初始化 3.3 从文本文件导入数据 3.4 数据修改 3.5 单元格格式设置 3.6 数据另存为文件 1 概述 QStandardItemModel是标准的以项数据&#xff08;itemdata&#xff09;为基础的…

【管理篇 / 恢复】❀ 08. 文件权限对macOS下用命令刷新固件的影响 ❀ FortiGate 防火墙

【简介】虽然上篇文章中成功的在macOS下刷新了固件&#xff0c;但是很多小伙伴在实际操作中碰到了无法成功的状况&#xff0c;我们来看看最常见的一种。 在/private/tftpboot目录拷贝另一个版本的固件文件&#xff0c;具体拷贝过程不再详述。 打开终端&#xff0c;输入命令 sud…

Do you know about domestic CPUs

Do you know about domestic CPUs CPU指令集国产CPU CPU指令集 国产CPU 参考文献 国产CPU之4种架构和6大品牌指令集及架构一文深入了解 CPU 的型号、代际架构与微架构国产GPU芯片厂商有哪些深入GPU硬件架构及运行机制详解服务器GPU架构和基础知识

编写一个弹跳小球的程序,小球在窗口中四处反弹(python)

import pygame import random# 初始化Pygame pygame.init()# 窗口尺寸 width 800 height 600# 创建窗口 screen pygame.display.set_mode((width, height)) pygame.display.set_caption("Bouncing Ball")# 小球初始位置和速度 ball_radius 20 ball_color (255, …

TCP和UDP的区别是什么

TCP和UDP是互联网协议中两个重要传输层协议。 一、工作原理 1.1 TCP TCP是一种面向连接的协议&#xff0c;通过三次握手建立可靠的连接。发送端将数据分割成多个TCP段&#xff0c;并通过IP进行传输。接收端接收到TCP后进行重组&#xff0c;并通过确认机制确保数据的可靠性。…

HUAWEI华为荣耀MagicBook X 15酷睿i5-10210U处理器集显(BBR-WAH9)笔记本电脑原装出厂Windows10系统

链接&#xff1a;https://pan.baidu.com/s/1YVcnOP5YKfFOoLt0z706rg?pwdfwp0 提取码&#xff1a;fwp0 MagicBook荣耀原厂Win10系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、华为/荣耀电脑管家等预装程序 文件格式&#xff1a;esd/wim/swm 安装…

docker 部署haproxy cpu占用特别高

在部署mysql 主主高可用时&#xff0c;使用haproxy进行负载&#xff0c;在服务部使用的情况下发现服务器cpu占比高&#xff0c;负载也高&#xff0c;因此急需解决这个问题。 1.解决前现状 1.1 部署配置文件 cat > haproxy.cfg << EOF globalmaxconn 4000nbthrea…

解码 Elasticsearch 查询 DSL:利用 Elasticsearch 中的 has_child 和 has_parent 查询进行父子文档搜索

今天&#xff0c;让我们深入研究 has_child 查询和 has_parent 查询&#xff0c;这将帮助我们将 2 个不同的文档组合到一个索引中&#xff0c;从而使我们能够将它们与关系关联起来。 这样做会对我们搜索相关文档时有很大帮助。 在使用 has_child 及 has_parent 这种关系时&…

移动端-vue-BScroll用法教程

移动端-vue-BScroll用法教程 简介官网安装使用移动端滚动使用移动端联合滚动实现懒加载页面使用 扩展-什么是防抖和节流相同点区别 简介 BetterScroll 是一款重点解决移动端&#xff08;已支持 PC&#xff09;各种滚动场景需求的插件&#xff0c;是最接近与原生的滚动插件&…

51单片机定时/计数器相关知识点

51单片机定时/计数器相关知识点 结构组成 51单片机的定时/计数器中有两个寄存器&#xff1a; T0&#xff1a;低位&#xff1a;TL0&#xff08;字节地址8AH&#xff09;高位&#xff1a;TH0&#xff08;字节地址8CH&#xff09;T1&#xff1a;低位&#xff1a;TL1&#xff08…

【教学类-综合练习-03】20231214 大3班 数字加减法练习(数字火车、X—Y加法减法、X乘法、X—Y数字分合)

第二次来大3班投放综合学具 第二次做综合题&#xff0c;大3班孩子选择的内容就跟更多了 今天高手没有来&#xff0c;每人能做“加减乘”

vue封装组件(一)标签和下拉框组合实现添加数据

背景: 最近接入短剧内容&#xff0c;需要添加短剧合作方。在详情页需要支持添加组件 方案一&#xff1a;标签tag加上输入框实现添加数据。图片见下 这个是刚开始做的&#xff0c;后来产品觉得这样会造成随意修改数据&#xff0c;需要改成下拉框形式添加 方案二&#xff1a;标签…

算法每日一题:在链表中插入最大公约数 | 链表 | 最大公约数

hello&#xff0c;大家好&#xff0c;我是星恒 今天的题目是有关链表和最大公约数的题目&#xff0c;比较简单&#xff0c;核心在于求解最大公约数&#xff0c;我们题解中使用辗转相除法来求解&#xff0c;然后我们会在最后给大家拓展一下求解最大公约数的四个方法&#xff0c;…

vue3学习 【2】vite起步和开发工具基本配置

vite的简介 官方文档 刚起步学习&#xff0c;所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18&#xff0c;可以参考上一篇文章的安装nvm&#xff0c;用来进行多版本的node管理。 vite安装与使用 npm create vitela…

Android两个APP之间跳转+手机图标修改

APP之间跳转 两个APP之间跳转同样使用Intent进行跳转&#xff0c;将需要跳转的APP都下载到手机中&#xff0c;通过主APP调用需要跳转的APP包名进行跳转。 最好在其中加上try-catch语句&#xff0c;当需要跳转的APP不存在时进行错误抓取。 代码如下&#xff1a; Intent mInten…

MySQL索引简介(包含索引优化,索引失效,最左前缀简洁版)

一、索引的基本概念 1.什么是索引 索引是一种数据结构&#xff0c;用于快速查找和访问数据库中的数据。它类似于书本的目录&#xff0c;可以帮助数据库管理系统快速定位到存储数据的位置。通过创建索引&#xff0c;我们可以加快数据库的查询速度并提高系统的性能。索引可以基于…

Notepad++ v7.7.1 安装及添加插件

1、notepad_v7.7.1.zip npp.7.7.1.Installer.x64.exe npp.7.7.1.Installer.x86.exe notepad_v7.7.1.ziphttps://www.123pan.com/s/VTMXjv-X6H6v.html 2、notepad插件包_64bit_4.zip ComparePlugin ---->文件对比插件 ComparePlugin.dllNppFTP ---->FTP、FTPES和SFTP …