一、分布式系统面临的问题spring
(1)服务雪崩后端
多个微服务之间调用的时候,假设微服务A调用微服务B和C,微服务B和C又调用其它的微服务,这就是所谓的“扇出”。若是扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用愈来愈多的系统资源,进而引发系统崩溃,引发所谓的“雪崩效应”。服务器
对于高流量的应用来讲,单一的后端依赖可能会致使全部服务器上的全部资源都在几秒钟内饱和。比失败更糟糕的是,这些应用程序还可能致使服务之间的延迟增长,备份队列,线程和其余系统资源紧张,致使整个系统发生更多的级联故障。这些都表示须要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不能取消整个应用程序或系统。app
(2)解决方案框架
这种模式主要是参考电路熔断,若是一条线路电压太高,保险丝会熔断,防止火灾。放到咱们的系统中,若是某个目标服务调用慢或者有大量超时,此时,熔断该服务的调用,对于后续调用请求,不在继续调用目标服务,直接返回,快速释放资源。若是目标服务状况好转则恢复调用。分布式
这种模式就像对系统请求按类型划分红一个个小岛的同样,当某个小岛被火烧光了,不会影响到其余的小岛。例如:能够对不一样类型的请求使用线程池来资源隔离,每种类型的请求互不影响,若是一种类型的请求线程资源耗尽,则对后续的该类型请求直接返回,再也不调用后续资源。这种模式使用场景很是多,例如将一个服务拆开,对于重要的服务使用单独服务器来部署,再或者公司最近推广的多中心。ide
上述的熔断模式和隔离模式都属于出错后的容错处理机制,而限流模式则能够称为预防模式。限流模式主要是提早对各个类型的请求设置最高的QPS阈值,若高于设置的阈值则对该请求直接返回,再也不调用后续资源。这种模式不能解决服务依赖的问题,只能解决系统总体资源分配问题,由于没有被限流的请求依然有可能形成雪崩效应。微服务
二、服务熔断测试
(1)概念ui
当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回"错误"的响应信息。当检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制经过Hystrix实现。Hystrix会监控微服务间调用的情况,当失败的调用到必定阈值,缺省是5秒内20次调用失败就会启动熔断机制。
(2)实现
添加依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-hystrix</artifactId> </dependency>
配置文件中修改服务的名称:
instance: instance-id: my8001-hystrix prefer-ip-address: true
定义Controller:
一旦调用GET方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法。可是,此种方式会存在一个问题就是每个方法都须要一个处理
@RestController public class DeptController { @Autowired private DeptService service = null; @RequestMapping(value="/dept/get/{id}",method= RequestMethod.GET) @HystrixCommand(fallbackMethod = "processHystrix_Get") public Dept get(@PathVariable("id") Long id) { Dept dept = this.service.get(id); if(null == dept) { throw new RuntimeException("该ID:"+id+"没有没有对应的信息"); } return dept; } public Dept processHystrix_Get(@PathVariable("id") Long id) { return new Dept().setDeptno(id) .setDname("该ID:"+id+"没有没有对应的信息,null--@HystrixCommand") .setDb_source("no this database in MySQL"); } }
在启动类中添加对hystrixR熔断机制的支持
@EnableCircuitBreaker
三、服务降级
(1)概念
总体资源不足,将某些服务先关掉,待渡过难关,再从新开启,服务降级是在客户端完成的。
(2)实现
新建一个实现了FallbackFactory接口的类DeptClientServiceFallbackFactory,该接口是专门处理异常的,与上面的服务熔断处理异常的方式相比,此种方式实现了逻辑与异常处理业务的分离
@Component public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> { @Override public DeptClientService create(Throwable throwable) { return new DeptClientService() { @Override public Dept get(long id) { return new Dept().setDeptno(id) .setDname("该ID:" + id + "没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭") .setDb_source("no this database in MySQL"); } @Override public List<Dept> list() { return null; } @Override public boolean add(Dept dept) { return false; } }; } }
在API模块中的业务接口的注解中添加属性:
@FeignClient(value = "PROVIDER",fallbackFactory=DeptClientServiceFallbackFactory.class) public interface DeptClientService { @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET) public Dept get(@PathVariable("id") long id); @RequestMapping(value = "/dept/list",method = RequestMethod.GET) public List<Dept> list(); @RequestMapping(value = "/dept/add",method = RequestMethod.POST) public boolean add(Dept dept); }
feign: hystrix: enabled: true
(3)测试
在只启动一个服务的提供者(8001)的状况下,可以正常访问,当讲该服务关闭的时候可以给出提示信息。也就是说在服务端不可用的时候客户端可以获得提示,而不是挂起。