先来了解一个概念:雪崩
就是一条长链路中,其中某个服务失败了,导致整个链路都失效了。
Hystrix熔断器就是为了防止这种情况出现而诞生的。
隔离
线程池隔离:
如果没有线程池隔离(不存在线程池BCD),只有一个线程池A,那么如果C服务挂了,所有的线程池里的线程都进入到了C,可是由于C服务挂了,根本不会把线程还回来啊,所以就会导致线程池根本没线程了,进而也都无法调用BD服务了,这就出现了雪崩。而这时候我们使用线程池隔离,为每个服务都开设属于他们的线程池,那么ThreadPool-C因为服务C挂了之后,最多只耗尽ThreadPool-C中的线程而已。
信号量隔离就很好理解了,我只允许40个“信号量”进入C服务,多了我就不给进了,所以当进入C服务的线程数量达到40个的时候,我们就停止分发线程给C服务了。
降级
如果一个服务不可用,那么我们就会对他实施“降级”,避免雪崩的发生。比如说A请求C服务,C服务处理不了,那么C取而代之返回一个“我在升级维护”或者默认的数据,那么也能避免程序走不下去。同时,如果A请求C的途中挂了(由于网络连接问题什么的),根本接收不到来自C的降级方案,那么我们就会调用A的降级方案。总之就是个Plan B的概念。
如何使用降级:
第一步,导入坐标:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
第二步,在启动类打开hystrix的功能
@EnableEurekaClient //该注解 在新版本中可以省略
@SpringBootApplication
@EnableCircuitBreaker//启动熔断器功能
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class,args);
}
}
第三步,编写降级方法(记住!他必须与原方法的签名保持一致,除了方法名)
public Goods findOneFallBack(int id){
Goods goods = new Goods();
goods.setTitle("老子是降级后的");
return goods;
}
第四步,将该方法注册到对应的需要该降级方案的方法上去
@HystrixCommand(fallbackMethod = "findOneFallBack")
@GetMapping("/findOne/{id}")
public Goods findOne(@PathVariable("id") int id){
Goods goods = goodsService.findOne(id);
int i = 1/0;//故意制造了个异常
goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
return goods;
}
至此,就调用完成了。
额外补充一个设置超时属性的配置方法吧。
消费端的写法略有不同:
第一步,在配置中打开hystrix的功能
feign:
hystrix:
enabled: true #开启熔断器
第二步,编写降级方法(记住!继续集成接口并实现对应的方法)
@Component
public class GoodsFeignClientFallback implements GoodsFeignClient {
@Override
public Goods findGoodsById(int id) {
Goods goods = new Goods();
goods.setTitle("降级");
return goods;
}
}
第三步,将该方法注册到对应的需要该降级方案的方法上去(通过Fallback传入字节码文件)
@FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
public interface GoodsFeignClient {
@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);
}
熔断
其实就是单位时间里错误出现太多了(包括频繁的降级),某个服务方就会被完全暂停提供服务,不管他的部分功能是否可以被访问到。
熔断的机制默认是开启的,所以你不写也是会有这个机制的,和降级不同。
5秒内失败达到阈值,就熔断,哪怕其中可以访问的请求也停止,默认规定时间之后再恢复回来。