随着前6章的学习,我们已经构建了一个基本的微服务,并通过Feign实现了远程调用,代码可读性也通过Feign远程调用带来了大幅提高。微服务基础是分布式的,在日常运行过程中就会存在一个问题,某个分布在异地的微服务由于网络或者其他问题出现了无法调用的情况时,我们如何应对?
分布式系统无法避免的就是如何解决在分布式情况下,实现对各个部署部分保障容错。举个例子:目前由于疫情肆虐,大家在很多场所都需要出示健康码,特别是异地出行。当我出差去西安,需要出示健康码,西安本地并没有我的相关行程、疫苗数据,需要调用湖南的相关服务来获取我的相关信息,如果湖南健康码服务出现了网络异常导致无法调用,那么西安本地服务就会不断调用湖南服务;如果出现了以上这种情况,我们应该如何处理?
在Java中每次服务调用都意味着初始化一个新的请求线程,如果远程调用失败继续请求,那么每次请求都会初始化一个新的请求线程,且每个请求线程都要等到所请求的服务出现超时才会被释放,那么就会带来大量计算资源被浪费并且导致阻塞。在任何分布式服务中,容错就成为了必须要解决的问题。
在分布式系统中常见的容错机制有以下三种机制:
1.超时
超时机制较为简单粗暴,也是最常见的容错机制。每个请求线程如果超过设置的请求时长,则立即释放请求线程,从而保障资源被及时释放,防止应用崩溃。
2.舱壁模式
参观大型船舶时或者看战争片,大家都会发现一般大型船只都有损管部门,损管部门往往需要在出现灾难时关闭水密舱,水密舱就是典型的容灾设计。A服务设计一个线程池,容纳50个请求线程,当新的请求线程被创建时立即释放原有的请求线程,当B服务阻塞时,A服务的线程池仅仅只容纳50个请求线程可以保障A服务不会因为B服务的问题导致崩溃。
3.断路器模式
断路器就是我们日常生活中配电箱中的断路器,当负载超过一定程度自动断路,从而保障其他电器不受影响。但是断路器模式有一个问题就是,必须通过手动恢复来使其继续工作。在微服务的世界中,断路器被设计为一个具备自动恢复功能的断路器。
Martin Fowler,63年的老爷子,教父级别,看看他的书,断路器这个概念就是他搞出来的!
其典型的工作原理如下所示:
注意:
断路器一共具备三种状态:
- 断路器打开:所有请求无法直接连通至其他微服务,将得到一个错误请求结果。
- 断路器关闭:请求已正确完成,并得到了其他微服务的正反馈。
- 断路器半开:此状态下断路器自动测试所调用的服务是否已具备调用条件,这个状态一般是自动开启的,也是一个瞬时状态。