由于一个服务不可用,有可能会导致一连串的微服务跟着不可用[服务器支持的线程和并发数有限,请求一直阻塞,会导 致服务器资源耗尽,从而导致所有其它服务都不可用], 形成级联失败,最终会导致服务雪崩问题。针对服务雪崩,有如 下几种解决方案:
- 方案 1:超时处理:设定超时时间,请求超过一定时间没有响应就返回错误信息,不会无休止等待
- 方案 2: 仓壁模式, 仓壁模式来源于船舱的设计
- 方案 3: 断路器模式:由断路器统计业务执行的异常比例,如果超出阈值则会熔断该业务,拦截访问该业务的一切请求。 断路器会统计访问某个服务的请求数量,异常比, 当发现访问服务 D 的请求异常比例过高时,认为服务 D 有导致雪崩的 风险,会拦截访问服务 D 的一切请求,形成熔断
- 方案 4: 限流,流量控制:限制业务访问的 QPS,避免服务因流量的突增而故障
微服务之间相互调用,因为调用链中的?个服务故障,引起整个链路都无法访问的情况。
限流是对服务的保护,避免因瞬间高并发流量而导致服务故障,进而避免雪崩。是?种预防措施。
超时处理、线程隔离、降级熔断是在部分服务故障时,将故障控制在?定范围,避免雪崩。是?种补救措施

我使用的是docker安装方式,大家也可以自行用其他的方式.安装好了以后直接在浏览器访问:http://192.168.137.72:8858/
https://sentinelguard.io/zh-cn/index.html
- 流控:流量控制
- 降级:降级熔断
- 热点:热点参数限流,是限流的?种
- 授权:请求的权限控制







- 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
- 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
- 链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流
@Value("${server.port}")private String port;@GetMapping("/findById")public User findById(Integer id) { User user = userService.findById(id); return user;}@GetMapping("/write")public String write() { return port;}


注意:测试后面的规则,最好把前面的规则删除掉,不然出现问题自己都蒙了......
@Override@SentinelResource // Sentinel 默认只标记 Controller 中的方法为资源,如果要标记其它方法,需要利用@SentinelResource 注解public void hello() { System.out.println("你好");} @GetMapping("/write")public String write() { userService.hello(); return port;}@GetMapping("/read")public String read() { userService.hello(); return port;}sentinel: web-context-unify: false #如果不关闭,所有controller层的方法对service层调用都认为是同一个根链路

- 直接:对当前资源限流
- 关联:高优先级资源触发阈值,对低优先级资源限流
- 链路:阈值统计时,只统计从指定资源进入当前资源的请求,是对请求来源的限流



@GetMapping("/findById") public Movie findById(@RequestParam("id") Integer id){ try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(port); return movieService.findById(id); }
@SentinelResource(value = "hot")@GetMapping("/resource/{hid}")public String testHotResource(@PathVariable("hid") Long hid) { System.out.println(hid); return port;}
参数为1时,每秒请求数最大为3
参数为2是,每秒请求数最大为5
虽然限流可以尽量避免因高并发而引起的服务故障,但服务还会因为其它原因而故障。而要将这些故障控制在一定范围, 避免雪崩,就要靠线程隔离(舱壁模式)和熔断降级手段了。 不管是线程隔离还是熔断降级,都是对客户端(调用方)的保护。
- 1.线程池隔离 (Hystrix 两种隔离方式都支持)
- 2.信号量隔离(Sentinel 只支持信号量隔离)


hystrix: command: default: execution: isolation: strategy: Thread # 默认是Thread, 可选Thread(线程池隔离)|Semaphore(信号量隔离)
这里的线程数是:该资源能使用用的 tomcat 线程数的最大值。也就是通过限制线程数量,实现舱壁模式。
- 线程隔离的两种手段是?信号量隔离、线程池隔离
- 信号量隔离的特点是?基于计数器模式,简单,开销小
- 线程池隔离的特点是?基于线程池模式,有额外开销,但隔离控制更强
feign: sentinel: enabled: true # 开启feign对sentinel的支持package com.qbb.cloud2022.feign;import com.qbb.cloud2022.com.qbb.springcloud.entity.Movie;import org.springframework.stereotype.Component;/** * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit) * @version 1.0 * @date 2022-04-07 23:34 * @Description: */@Componentpublic class FeignMovieServiceFallBack implements FeignMovieService { @Override public Movie findById(Integer id) { Movie movie = new Movie(-1, "网络异常,请稍后再试~~~~"); return movie; }}@FeignClient(value = "sentinel-provider-user9101",fallback = FeignMovieServiceFallBack.class)
feign: sentinel: enabled: true # 开启feign对sentinel的支持package com.qbb.cloud2022.feign;import com.qbb.cloud2022.com.qbb.springcloud.entity.Movie;import feign.hystrix.FallbackFactory;import org.springframework.stereotype.Component;/** * @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit) * @version 1.0 * @date 2022-04-07 23:34 * @Description: */@Componentpublic class FeignMovieServiceFallBackFactory implements FallbackFactory { @Override public Object create(Throwable throwable) { throwable.printStackTrace(); return new Movie(-1, "网络异常,请稍后再试~~~~"); }}@FeignClient(value = "sentinel-provider-user9101",fallbackFactory = FeignMovieServiceFallBackFactory.class)
控制台直接报错
熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔 断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求

断路器熔断策略有三种:慢调用、异常比例、异常数
@GetMapping("/findById") public Movie findById(@RequestParam("id") Integer id) { if (id == 2) { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(port); return movieService.findById(id); }
- 慢调用比例:超过指定时?的调用为慢调用,统计单位时?内慢调用的比例,超过阈值则熔断
- 异常比例:统计单位时?内异常调用的比例,超过阈值则熔断
- 异常数:统计单位时?内异常调用的次数,超过阈值则熔断
