# spring-cloud-config-server **Repository Path**: M-N-A/spring-cloud-config-server ## Basic Information - **Project Name**: spring-cloud-config-server - **Description**: spring Cloud配置中心demo - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2023-09-10 - **Last Updated**: 2024-03-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # **限流** **解释:** 限流可以认为服务降级的一种,限流就是限制系统的输入和输出流量以达到保护系统的目的。 为了保证系统的稳定运行,一旦达到需要限制的阔值,就需要限制流量并采取一些措施以完成限制流量的目的。限流对某一时间窗口内的请求进行限制,保持系统的可用性和稳定性,防止因流量暴增而导致系统运行缓慢或宕机。 **限流的原因:** 互联网系统通常要面对大并发大流量的请求,在突发情况下(比如:秒杀、抢购),瞬时大流量会直接将系统打垮,无法对外提供服务。为了防止出现这种情况常见的解决方案之一是限流,当请求达到一定的并发数或速率,就进行等待、排队、降级、拒绝服务等。 ## 限流算法 1. **计数器限流** - 计数器限流算法最为简单粗暴,主要采用限制总并发数,比如数据库连接池大小、线程池大小、接口访问并发数等。 2. **漏桶算法** - 漏桶算法思路很简单,我们把水比作是请求,漏桶比作是系统处理能力极限,水先进入到漏桶里,漏桶里的水按一定速率流出,当流出的速率小于流入的速率时,由于漏桶容量有限,后续进入的水直接溢出(拒绝请求),以此实现限流。 3. **令牌桶算法** - 令牌桶算法的原理也比较简单,我们可以理解成医院的挂号看病,只有拿到号以后才可以进行诊病。系统会维护一个令牌(token)桶,以一个恒定的速度往桶里放入令牌(token), 这时如果有请求进来想要被处理,则需要先从桶里获取一个令牌(token),当桶里没有令牌(token)可取时,则该请求将被拒绝服务。令牌桶算法通过控制桶的容量、发放令牌的速率,来达到对请求的限制。 ## guava - https://zhuanlan.zhihu.com/p/621267375 # **Hystrix** ## 概念 - Hystrix 是一个用用于处理分布式系统的延迟和容错的开源库,可以保证一个服务出现故障时,不回导致整个系统出现雪崩效应,提高分布式系统弹性; - 作为“断路器”,在一个服务出现故障时,可以通过短路监控,返回一个可以处理的响应结果,保证服务调用线程不会长时间被占用,避免故障蔓延; ## **Hystrix作用** 1. **服务降级** - 服务出现故障时,给故障服务降级到事先准备好的故障处理结果,并将结果返回给服务消费者。 2. **服务熔断** - 熔断机制是应对服务雪崩的一种链路保护机制,当服务出现故障时,服务会进行降级,熔断该服务节点,迅速返回错误响应信息。当检测到服务安全访问正常时,恢复其链路节点 3. **服务隔离(服务限流)** - 判断线程池或者信号量是否已满,超出容量的请求直接降级,以达到限流的目的; ### **Hystrix隔离策略(资源隔离)** 1. **线程池隔离(默认策略)** ``` @Override @HystrixCommand(fallbackMethod = "handleError", commandKey = "hystrixTest", //commandKey,当前command的名称 groupKey = "hystrixTestGroup", groupKey:当前command所在的组。默认情况下根据group定义一个线程池,即同一个组的请求进入同一个线程池;也根据group聚合一些监控和报警信息等 commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1000000"), //execution.isolation.thread.timeoutInMilliseconds:隔离策略为THREAD时,执行的超时时间,单位ms @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD"), //execution.isolation.strategy:指定隔离策略。THREAD或SEMAPHORE @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000000000") //threadPoolKey:线程池的key,默认为group的名称 }, threadPoolKey = "hystrixTestThreadPool", threadPoolProperties = { @HystrixProperty(name = "coreSize", value = "5") //coreSize:线程池大小。默认10 }) public String hystrixTest() { return "a"; } ``` #### 优点: 1. 保护应用程序以免受来自依赖故障的干扰,指定依赖程序线程池饱和不会影响应用程序的其他部分; 2. 当引入新客户端lib时,即使发生问题,也是在lib中,不会影响其他内容; 3. 当依赖从故障恢复正常时,应用程序会立即恢复正常性能; 4. 当应用程序一些配置参数错误时,线程池的运行状态很快会检测到,同时可以动态属性进行实时纠正错误的参数配置; 5. 如果服务的性能有变化(增加/减少 时间、更改重试次数),需要实时调整,可以通过线程池指定状态属性修改,而且不影响其他调用请求; #### 缺点: - 线程池隔离的主要缺点是增加了计算机开销。每个命令的执行都在单独的线程完成,增加了排队、调度和上下文切换的开销。 3. **信号量隔离** ``` @HystrixCommand(fallbackMethod = "handleError", commandKey = "hystrixsemaphore", g roupKey = "hystrixTestGroup-one", commandProperties = { @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"), @HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests",value = "10"), //execution.isolation.semaphore.maxConcurrentRequests 配置信号量的大小,达到最大并发信号量时,后续请求被拒 }, threadPoolKey = "SemaphoreThreadPool", threadPoolProperties = { @HystrixProperty(name = "coreSize", value = "10") }) ``` #### 优点 1. 信号量隔离通过设置信号量来限制对任何给定依赖的并发调用量; 2. 信号量不需要切换线程,避免了不必要的开销; #### 缺点 - 信号量隔离不支持异步,也不支持超时,当请求服务不可用时,信号量会控制超出限制的请求立即返回,可能出现长时间的等待; ### **Hystrix的设计原则** 1. 防止单个服务的故障耗尽整个服务的Servlet容器的线程池资源; 2. 快速失败机制,如果某个服务出现故障,则调用该服务的请求快速失败,而不是线程等待; 3. 提供回退方案,在请求发生故障时,提供设定好的回退方案; 4. 使用熔断器机制,防止故障扩散到其他服务; 5. 提供熔断器的监控组件(Hystrix DashBoard),可以实时监控熔断器的状态; ### **Hystrix的工作机制** 1. 当服务的某个API接口的失败次数在一定时间内小于设定的阔值时,熔断器处于关闭状态,API接口正常提供服务; 2. 当该API接口处理请求的失败次数在一定时间内大于设定的阔值,Hystrix判断该API接口故障,开启熔断器,API接口执行快速失败逻辑,不执行业务逻辑,请求线程不会处于阻塞状态;失败的业务逻辑走指定的`fallbackMethod` 方法 3. 处于打开状态的熔断器在一定时间后会处于半大开状态,将一部分数量请求执行正常的业务逻辑,剩余的请求执行快速失败逻辑; 4. 若执行正常逻辑的业务的请求失败了,则熔断器继续打开,若成功了,则熔断器关闭。 ### **熔断器** 熔断器配置,Circuit Breaker 主要6个参数: 1. `circuitBreaker.enable` #是否开启熔断器,默认TRUE 2. `circuitBreaker.forceOpen` #熔断器强制打开,始终保持打开状态,不关注熔断器的实际状态。默认值 FALSE 3. `circuitBreaker.forceClose` #熔断器强制关闭,始终保持关闭状态,不关注熔断开关的实际状态。默认值 FALSE 4. `circuitBreaker.errorThresholdPercentage` #错误率,默认值为50%,当出现出错比例大于错误率的数值的情况,触发熔断器; 5. `circuitBreaker.requestVolumeThreshold` #默认值20,一段时间内至少有20个请求才进行`errorThresholdPercentage` 计算。(例:当一段时间内有19个请求,且全部请求都失败,错误率100%,可因为总请求数不满20个,熔断器不会开启) 6. `circuitBreaker.sleepWindowMillisSeconds` #半开启试探睡眠时间,默认值5000ms。(例:当熔断器开启5000ms后,会尝试放行部分流量进行试探,以确定服务是否恢复正常) ### **Hystrix的回退降级** **目的:** 在事务高峰期,为了保证核心服务的正常运行,需要停掉一些不太重要的业务,或某些服务不可用时,执行备用逻辑从故障服务快速失败或快速返回,以保障主体业务不受影响。 **Hystrix走服务降级逻辑的情况:** 1. 执行construct或run抛出异常; 2. 熔断器打开导致命令短路; 3. 命令的线程池和队列或信号量超额,命令被拒绝; 4. 命令执行超时; **Hystrix降级回退方式** 1. Fail Fast快速失败; - 快速失败是最普通的命令执行方法,命令没有重写降级逻辑。如果命令发生任何类型的故障,将直接抛出异常; 2. Fail Fast无声失败; - 无声失败指在降级中通过返回null,空Map,空List或其他类似的响应来完成; 3. FallBack:Static - 指在降级方法中返回静态默认值。这不会导致服务以“无声失败”的方式被删除,而是选择默认的失败逻辑; 4. FallBack:Stubbed - 当命令返回一个包含多个字段的复合对象时,适合以Stubbed的方式回退; 5. FallBack:Cache via NetWork - 从缓存服务中查询旧数据版本。(由于会发起远程调用,建议重新封装Command,使用不同TheadPoolKey,与主线程池进行隔离) 6. Primary+Secondary with Fallback - 有时系统具有两种行为-主要和次要,或主要和故障转移。主要和次要逻辑涉及到不同的网络调用和业务逻辑,所以需要将主次逻辑封装在不同的Command中,使用线程池进行隔离。为了实现主从逻辑切换,可以将主次command封装在外观HystrixCommand的run方法中,并结合配置中心设置的开关切换主从逻辑。由于主次逻辑都是经过线程池隔离的HystrixCommand,因此外观HystrixCommand可以使用信号量隔离,而没有必要使用线程池隔离引入不必要的开销。 - (场景):当系统升级新功能,如果新版本的功能出现问题,通过开关控制降级调用旧版本的功能; ### Hystrix指令参考网址 - https://blog.csdn.net/truelove12358/article/details/117998125 ## Hystrix参考网址 - https://blog.csdn.net/weixin_50616848/article/details/124542186 - http://www.linkedkeeper.com/1157.html - https://blog.csdn.net/qq_34561892/article/details/128022263 - https://blog.csdn.net/weixin_43696529/article/details/107746126 - https://www.sohu.com/a/465169669_827544 - http://www.uml.org.cn/wfw/201906063.asp - https://c.biancheng.net/springcloud/hystrix.html ## resilience4j spring-cloud-starter-circuitbreaker-resilience4j # feign 和 openfeign ## **Feign** - `Feign`是`SpringCloud`组件中的一个轻量级RESTful的HTTP服务客户内置的`Ribbon` ,用来做客户端的负载均衡,去调注册中心的服务。`Feign`使用方式:使用`Feign`的注解定义接口,调用该接口,就可以调用服务; ### **Feign的作用** 1. Feign是一种声明式服务调用组件,在`RestTemplate`的基础上做了进一步的封装,通过`Feign`,开发者只要声明一个接口并通过注解进行简单的配置即可实现对HTTP接口的绑定; 2. 通过`Feign`,可以像调用本地方法一样来调用远程服务,且完全感觉不到有是在进行远程调用; 3. `Feign`支持多种注解,有自带注解以及`JAX-RS`注解等,但Feign并不支持`SpringMVC`注解; ## **openFeign** - **解释:** `openFeign`是`SpringCloud`在`Feign`的基础上支持了`SpringMVC`的注解,且具备`Feign`的所有功能,如`RequestMapping`及其衍生类注解;@`FeignClient` 可以解析`SpringMVC`的`@RequestMapping`注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务; ### **`openFeign`在`consumer`消费者中的传参方式** 1. 传JSON数据 ```java @FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 参数默认是@RequestBody标注的,这里的@RequestBody可以不填 * 方法名称任意 */ @PostMapping("/openfeign/provider/order2") Order createOrder2 (@RequestBody Order order); } ``` 2. POJO表单参数 ```java @FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 参数默认是@RequestBody标注的,如果通过POJO表单传参的,使用@SpringQueryMap标注 */ @PostMapping("/openfeign/provider/order1") Order createOrder1 (@SpringQueryMap Order order); } ``` 3. URL中携带参数 ```java @FeignClient(value = "openFeign-provider") public interface OpenFeignService { @GetMapping("/openfeign/provider/test/{id}") String get (@PathVariable("id") Integer id); } ``` 4. 普通表单参数 ```java @FeignClient(value = "openFeign-provider") public interface OpenFeignService { /** * 必须要@RequestParam注解标注,且value属性必须填上参数名 * 方法参数名可以任意,但是@RequestParam注解中的value属性必须和provider中的参数名相同 */ @PostMapping("/openfeign/provider/test2") String test (@RequestParam("id") String arg1, @RequestParam("name") String arg2); } ``` ### `openfeign`超时 `openfeign`的默认连接超时时间是10S,默认读超时时间是60S feign.client.config.default.connectTimeout=3000 # default 设置的全局超时时间,指定服务名称可以设置单个服务的超时时间 feign.client.config.default.readTimeout=3000 ### `openfeign`常用注解 1. `@FeignClient` - 说明:用于`OpenFeign`组件对`@RequestMapping`注解的接口解析,并以动态代理的方式生产实现类,实现负载均衡和服务调用; 2. `@EnableFeignClients` - 用于开启OpenFeign的功能,当`SpringCloud`项目启动时,会扫描被`@FeignClient`修饰的接口类,并生成相应的代理实现类注册到Spring容器中; 3. `@RequestMapping` - SpringMVC注解,在SpringMVC中使用该注解映射请求,通过它来指定控制器(`Controller`类)可以处理哪些接口请求; 4. `@GetMapping` - SpringMVC注解,用来映射GET请求,是一个组合注解,相当于 @RequestMapping(method = RequestMethod.GET); 5. `@PostMapping` - SpringMVC注解,用来映射POST请求,是一个组合注解,相当于 @RequestMapping(method = RequestMethod.POST); ### openfeign 开启 hystrix 熔断机制,旧版本使用 feign.hystrix.enabled 新版本使用:feign.circuitbreaker.enabled ### **openfeign参考** - https://blog.csdn.net/qq_40811542/article/details/130581397 - https://blog.csdn.net/ldw201510803006/article/details/126414836 - https://c.biancheng.net/springcloud/open-feign.html # **sentinel** ## sentinel控制台下载及打包 1. 下载源码:`git clone https://github.com/alibaba/Sentinel.git` 2. 打包命令: - `cd Sentinel` - `mvn clean package -Dmaven.test.skip=true` ## [`Sentinel`特性](https://blog.csdn.net/truelove12358/article/details/107507455) 1. 轻量级,高性能 :核心 sentinel-core 没有任何多余依赖,打包后只有不到 200KB,非常轻量级。开发者可以放心地引入 sentinel-core 而不需担心依赖问题。同时,Sentinel 提供了多种扩展点,用户可以很方便地根据需求去进行扩展,并且无缝地切合到 Sentinel 中。 2. 流量控制: Sentinel 可以针对不同的调用关系,以不同的运行指标(如 QPS、并发调用数、系统负载等)为基准,对资源调用进行流量控制,将随机的请求调整成合适的形状。Sentinel 支持多样化的流量整形策略,在 QPS 过高的时候可以自动将流量调整成合适的形状。 1. 直接拒绝模式:即超出的请求直接拒绝。 2. 慢启动预热模式:当流量激增的时候,控制流量通过的速率,让通过的流量缓慢增加,在一定时间内逐渐增加到阈值上限,给冷系统一个预热的时间,避免冷系统被压垮。 3. 匀速器模式:利用 Leaky Bucket 算法实现的匀速模式,严格控制了请求通过的时间间隔,同时堆积的请求将会排队,超过超时时长的请求直接被拒绝。Sentinel 还支持基于调用关系的限流,包括基于调用方限流、基于调用链入口限流、关联流量限流等,依托于 Sentinel 强大的调用链路统计信息,可以提供精准的不同维度的限流。 3. 系统负载保护 :Sentinel 对系统的维度提供保护,负载保护算法借鉴了 TCP BBR 的思想。当系统负载较高的时候,如果仍持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。 4. Sentinel 提供 HTTP API 用于获取实时的监控信息,如调用链路统计信息、簇点信息、规则信息等。如果用户正在使用 Spring Boot/Spring Cloud 并使用了Sentinel Spring Cloud Starter,还可以方便地通过其暴露的 Actuator Endpoint 来获取运行时的一些信息,如动态规则等。 ## `Sentinel`工作原理 1. **资源:** 只要通过Sentinel API 定义的代码,就是资源,能够被Sentinel保护起来 2. **规则:** 围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整; ## `Sentinel`功能和设计理念 1. 流量控制 - 资源的调用关系,例如资源的调用链路,资源和资源之间的关系; - 运行指标,例如QPS、线程池、系统负载等; - 控制的效果,例:直接限流、冷启动、排队等; 2. 熔断降级 - `Sentinel` 和 `Hystrix` 的原则一致:当调用链路中某个资源出现不稳定,例如,表现为timeout,异常比例升高的时候,就对当前资源调用进行限制,并让请求快速失败,避免影响到其他资源; - 在限制手段上,`Sentinel`和`Hystrix`采用完全不一样的方法 - `Hystrix` 通过线程池的方式,来对依赖(API)进行隔离。好处是资源和资源之间做到了最彻底的隔离。缺点是增加了线程的切换成本,还要预先给各个资源做线程池的大小分配。 - `Sentinel`采取两种手段:`通过并发线程数进行限制` 和 `通过响应时间对资源做出降级` 处理 3. 系统负载保护 - `Sentinel` 同时提供系统维度的自适应保护能力,让系统入口流量和系统负载达到一个平衡,保证系统在能力范围内处理最多的请求。 ## `Sentinel`实践 - 模板 ``` Entry entry = null; // 务必保证 finally 会被执行 try { // 资源名可使用任意有业务语义的字符串,注意数目不能太多(超过 1K),超出几千请作为参数传入而不要直接作为资源名 // EntryType 代表流量类型(inbound/outbound),其中系统规则只对 IN 类型的埋点生效 entry = SphU.entry("自定义资源名"); // 被保护的业务逻辑 // do something... } catch (BlockException ex) { // 资源访问阻止,被限流或被降级 // 进行相应的处理操作 } catch (Exception ex) { // 若需要配置降级规则,需要通过这种方式记录业务异常 Tracer.traceEntry(ex, entry); } finally { // 务必保证 exit,务必保证每个 entry 与 exit 配对 if (entry != null) { entry.exit(); } } ``` ### `Sentinel`资源保护方式 1. 基于API实现`SphU.entry(RESOURCE_NAME)` - **缺点** - 业务侵入性强,需要在`controller`层写入非业务代码; - 配置不灵活,若需要添加新的受保护资源,需要手动添加 init 方法来添加流控规则; 1. 依赖及源码 ```xml com.alibaba.csp sentinel-core 1.8.5 ``` ```java // 源码 @Slf4j @RestController @RequestMapping("demo") public class DemoController { private static final String RESOURCE_NAME = "demo"; @RequestMapping(value = "/test") public String test () { try (Entry entry = SphU.entry(RESOURCE_NAME)) { // 被保护的逻辑 log.info("hello world"); return "hello world"; } catch (BlockException ex) { // 处理被流控的逻辑 log.info("blocked!"); return "被流控了"; } } /** * 定义流控规则 */ @PostConstruct private static void initFlowRules () { List rules = new ArrayList<>(); FlowRule rule = new FlowRule(); //设置受保护的资源 rule.setResource(RESOURCE_NAME); // 设置流控规则 QPS rule.setGrade(RuleConstant.FLOW_GRADE_QPS); // 设置受保护的资源阈值 // Set limit QPS to 20. rule.setCount(1); rules.add(rule); // 加载配置好的规则 FlowRuleManager.loadRules(rules); } } ``` 2. 基于注解方式`@SentinelResource` 1. 依赖 ```xml com.alibaba.csp sentinel-annotation-aspectj 1.8.5 ``` 2. 配置切面支持 ```java @Configuration public class SentinelAspectConfiguration { @Bean public SentinelResourceAspect sentinelResourceAspect () { return new SentinelResourceAspect(); } } ``` 3. 逻辑@sentinelResource,并配置blockHandler和fallback ```java @Slf4j @RestController @RequestMapping("annotation") public class AnnotationController { @SentinelResource(value = "annotation", blockHandler = "handleException", fallback = "fallbackException") @RequestMapping("/test") public String test () { int i = 1 / 0; return "helloworld"; } public String handleException (BlockException ex) { return "被流控了"; } public String fallbackException (Throwable t) { return "被异常降级了"; } @RequestMapping(value = "/findOrderByUserId/{id}") @SentinelResource(value = "findOrderByUserId", fallback = "fallback", fallbackClass = ExceptionUtil.class, blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class ) public R findOrderByUserId (@PathVariable("id") Integer id) { } } ``` 4. 编写ExceptionUtil,如果指定了class,则方法必须是static方法 ```java public class ExceptionUtil { public static R fallback (Integer id, Throwable e) { return R.error(-1, "===被异常降级啦==="); } public static R handleException (Integer id, BlockException e) { return R.error(-2, "===被限流啦==="); } } ``` 5. 流控规则设置可以通过`Sentinel dashboard`配置 - 客户端接入`sentinel dashboard`控制台 1. 依赖 ```xml com.alibaba.csp sentinel-transport-simple-http 1.8.5 ``` 2. 客户端启动JVM参数 - 模板:`-Dcsp.sentinel.dashboard.server=sentinel.dashboard.host:sentinel.dashboard.port` - 例:`-Dcsp.sentinel.dashboard.server=localhost:8080` 6. 注解实现类 SentinelResourceAspect 实现原理借助`Spring IOC` `@Aspect` `@Pointcut` `@Around` ```java @Aspect public class SentinelResourceAspect extends AbstractSentinelAspectSupport { public SentinelResourceAspect () { } @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)") public void sentinelResourceAnnotationPointcut () { } @Around("sentinelResourceAnnotationPointcut()") public Object invokeResourceWithSentinel (ProceedingJoinPoint pjp) throws Throwable { Method originMethod = this.resolveMethod(pjp); SentinelResource annotation = (SentinelResource) originMethod.getAnnotation(SentinelResource.class); if (annotation == null) { throw new IllegalStateException("Wrong state for SentinelResource annotation"); } else { String resourceName = this.getResourceName(annotation.value(), originMethod); EntryType entryType = annotation.entryType(); int resourceType = annotation.resourceType(); Entry entry = null; try { entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs()); Object var8 = pjp.proceed(); return var8; } catch (BlockException var15) { Object var18 = this.handleBlockException(pjp, annotation, var15); return var18; } catch (Throwable var16) { Class[] exceptionsToIgnore = annotation.exceptionsToIgnore(); if (exceptionsToIgnore.length > 0 && this.exceptionBelongsTo(var16, exceptionsToIgnore)) { throw var16; } else if (this.exceptionBelongsTo(var16, annotation.exceptionsToTrace())) { this.traceException(var16); Object var10 = this.handleFallback(pjp, annotation, var16); return var10; } else { throw var16; } } finally { if (entry != null) { entry.exit(1, pjp.getArgs()); } } } } } ``` 3. SpringCloud Alibaba整合`Sentinel` 1. 依赖 ```xml org.springframework.boot spring-boot-starter-actuator com.alibaba.cloud spring-cloud-starter-alibaba-sentinel ``` 2. 配置 ``` spring: application: name: mall-user-sentinel-demo cloud: nacos: discovery: server-addr: 127.0.0.1:8848 sentinel: transport: # 添加sentinel的控制台地址 dashboard: 127.0.0.1:8080 # 指定应用与Sentinel控制台交互的端口,应用本地会起一个该端口占用的HttpServer # port: 8719 #暴露actuator端点 management: endpoints: web: exposure: include: '*' ``` `AbstractSentinelInterceptor` 3. 在sentinel控制台设置流控规则 1. 资源名:API接口; 2. 针对来源:默认是default,当多个微服务调用该资源时,可以设置微服务名来针对指定的服务设置阔值; 3. 阔值类型:分为QPS和线程数;假设阔值为10。 1. QPS类型:对每秒访问接口的次数>10的进行限流; 2. 线程数:为接收请求该资源分配的线程数>就进行限流; 4. Sentinel Dashboard 控制台 1. **实时监控:** 监控接口的通过的QPS和拒绝的QPS 。同一个服务下的所有机器的簇点信息会被汇总,并且秒级地展示在"实时监控"下。实时监控仅存储 5 分钟以内的数据,如果需要持久化,需要通过调用实时监控接口来定制。 - 注意:请确保 Sentinel 控制台所在的机器时间与自己应用的机器时间保持一致,否则会导致拉不到实时的监控数据。 2. **簇点链路:** 用来显示微服务的所监控的API。簇点链路(单机调用链路)页面实时的去拉取指定客户端资源的运行情况。 - 注意: 簇点监控是内存态的信息,它仅展示启动后调用过的资源。 3. **流控规则:** 流量控制(flow control),其原理是监控应用流量的 QPS 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。同一个资源可以创建多条限流规则。FlowSlot 会对该资源的所有限流规则依次遍历,直到有规则触发限流或者所有规则遍历完毕。一条限流规则主要由下面几个因素组成,我们可以组合这些元素来实现不同的限流效果。 参考文档: https://github.com/alibaba/Sentinel/wiki/流量控制 转:https://blog.csdn.net/menxu_work/article/details/126987083 ### `Sentinel`参考 - https://blog.csdn.net/menxu_work/article/details/126987083 - https://blog.csdn.net/qq_42263280/article/details/128631130 - https://blog.csdn.net/qq_43599766/article/details/124889912 - https://blog.csdn.net/litianyu0730/article/details/125926732 # Dubbo ## Dubbo: 熔断-服务降级 1. **熔断的作用:** - Dubbo引用熔断(服务降级)的目的是为了防止provider无报错情况下长时间的响应 ,影响了其他服务进度,从而导致降低了consumer消费性能 2. **解决provider长时间未响应思路** : - 遇到长时间未响应及频繁超时等情况时,将consumer调用provider的请求,直接短路掉,不实际调用,而是直接返回一个mock的值。等provider服务恢复稳定之后,再重新调用 1. 一定是先降级优先级地的接口,两权相害取其轻 2. 如果服务链路整体没有性能特别差的点,比如就是外部流量突然激增,那么就从外到内开始降级。 3. 如果某个服务能检测到自身负载上升,那么可以从这个服务自身做降级。 3. **Dubbo服务降级使用** - mock机制 - 四种mock调用策略 1. `mock = "true"` - 指定 mock 策略为布尔类型,且为 true,当调用远程服务失败后, 就会执行调用其他provider - `@DubboReference(retries = 1,mock = "true")` 2. `mock = "具体的mock实现类"` - 指定 mock 策略为具体的 mock 实现类, 当调用远程服务失败时, 就会执行 mock 实现类的 sayHello 方法(调用其他provider). - `@DubboReference(mock = "com.cxl.service.UserService")` 3. `mock = "抛出自定义异常"` - 指定 mock 策略为抛出自定义异常, 当远程服务调用失败后, 会给服务消费者抛出自定义异常. - `@DubboReference(retries = 1,mock = "throw com.cxl.excep.CustomExcep")` 4. `mock="返回 mock 数据"` - 指定 mock 属性值为返回 mock 数据,当远程服务调用失败后,就会给服务消费者返回 null,(mock数据可以不写,默认返回null)。 - `@DubboReference(retries = 1,mock = "return null")` - fail:策略 1. `mock = "force:true"` - 指定 mock 策略为布尔类型,且为 true,当调用远程服务失败后, 就会执行调用其他provider - `@DubboReference(retries = 1,mock = "force:true")` 2. `mock = "force:执行的Mock实现类"` - 指定 mock 策略为具体的 mock 实现类, 当调用远程服务失败时, 就会执行 mock 实现类的 sayHello 方法(调用其他provider). - `@DubboReference(mock = "force:com.cxl.service.UserService")` 3. `mock = "force:抛出自定义异常"` - 指定 mock 策略为抛出自定义异常, 当远程服务调用失败后, 会给服务消费者抛出自定义异常. - `@DubboReference(retries = 1,mock = "force:throw com.cxl.excep.CustomExcep")` 4. `mock="force:返回 mock 数据"` - 指定 mock 属性值为返回 mock 数据,当远程服务调用失败后,就会给服务消费者返回 null,(mock数据可以不写,默认返回null)。 - `@DubboReference(retries = 1,mock = "force:return null")` 转自:[https://blog.csdn.net/m0_62866192/article/details/122045271](https://blog.csdn.net/m0_62866192/article/details/122045271) 参考:[https://blog.csdn.net/qq_40788718/article/details/107851593](https://blog.csdn.net/qq_40788718/article/details/107851593)