1. 熔断机制介绍
在介绍熔断机制之前,我们需要了解微服务的雪崩效应。在微服务架构中,微服务是完成一个单一的业务功能,这样做的好处是可以做到解耦,每个微服务可以独立演进。但是,一个应用可能会有多个微服务组成,微服务之间的数据交互通过远程过程调用完成。这就带来一个问题,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其它的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。
熔断机制是应对雪崩效应的一种微服务链路保护机制。我们在各种场景下都会接触到熔断这两个字。高压电路中,如果某个地方的电压过高,熔断器就会熔断,对电路进行保护。股票交易中,如果股票指数过高,也会采用熔断机制,暂停股票的交易。同样,在微服务架构中,熔断机制也是起着类似的作用。当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。当检测到该节点微服务调用响应正常后,恢复调用链路。
二、熔断结合Feign
必须满足两个条件,也就是触发熔断的条件,第一个条件是调用的微服务发生异常,第二个条件微服务宕机。
2.1、微服务提供者
package com.atguigu.springcloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atguigu.springcloud.entities.Dept;
import com.atguigu.springcloud.service.DeptService;
@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");
}
}
2.1、微服务消费者
package com.atguigu.springcloud.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.atguigu.springcloud.entities.Dept;
/**
* DeptClientServiceFallbackFactory:微服务出现熔断后的响应数据处理
* * @date 2018年4月21日
*/
@FeignClient(value = "MICROSERVICECLOUD-DEPT",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);
}
比如查询id为1111的数据,这个数据 数据库里面不存在,这样就会发生异常
{
"deptno": 123,
"dname": "该ID:123没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭",
"db_source": "no this database in MySQL"
}
三、熔断结合Ribbon
3.1、pom文件配置
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
3.2、启动类配置
package com.atguigu.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@SpringBootApplication
@EnableSwagger2
@EnableEurekaClient
@EnableCircuitBreaker /**启动熔断机制*/
public class DeptConsumer80_App
{
public static void main(String[] args)
{
SpringApplication.run(DeptConsumer80_App.class, args);
}
}
3.3、实现类配置
@SuppressWarnings("unchecked")
@RequestMapping(value = "/consumer/dept/list",method = {RequestMethod.GET})
@HystrixCommand(fallbackMethod = "listfallback")
public List<Dept> list()
{
int i=1/0;
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list", List.class);
}
private List<Dept> listfallback(){
System.out.println("进入熔断机制!");
List<Dept> result=new ArrayList<>();
return result;
}
上面HystrixCommand注解处理,比如微服务超时、宕机、发生异常,就会进入listfallback方法处理。目前还有一个疑问,难道没有一个统一的配置来处理这个吗?