一、Hystrix说明
1.服务雪崩效应:是一种因 服务提供者 的不可用导致 服务调用者 的不可用,并将不可用 逐渐放大 的过程。
1) A为服务提供者, B为A的服务调用者, C和D是B的服务调用者. 当A的不可用,引起B的不可用,并将不可用逐渐放大C和D时, 服务雪崩就形成了
2.雪崩原因:
1) 服务提供者不可用
a.硬件故障
a1.硬件损坏造成的服务器主机宕机
a2.网络硬件故障造成的服务提供者的不可访问
b.程序Bug
c.缓存击穿:缓存应用重启, 所有缓存被清空时,以及短时间内大量缓存失效时. 大量的缓存不命中, 使请求直击后端,造成服务提供者超负荷 运行,引起服务不可用
d.用户大量请求:在秒杀和大促开始前,如果准备不充分,用户发起大量请求造成服务提供者的不可用
2) 重试加大流量
a.用户重试:用户由于忍受不了界面上长时间的等待,而不断刷新页面甚至提交表单
b.代码逻辑重试:服务调用端的会存在大量服务异常后的重试逻辑
3) 服务调用者不可用
a.同步等待造成的资源耗尽:使用 同步调用 时, 会产生大量的等待线程占用系统资源. 一旦线程资源被耗尽,服务调用者提供的服务也将处 于不可用状态, 造成服务雪崩效应产生
二、Hystrix解决方式
Hystrix:通过服务熔断(也可以称为断路)、降级、限流(隔离)、异步RPC等手段控制依赖服务的延迟与失败
1.服务熔断
pom.xml:
<!-- hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
Controller层:
@RestController
public class DeptController
{
@Autowired
private DeptService service = null;
@RequestMapping(value = "/dept/get/{id}", method = RequestMethod.GET)
//一旦调用服务方法失败并抛出了错误信息后,会自动调用@HystrixCommand标注好的fallbackMethod调用类中的指定方法
@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)
{
Dept dept = new Dept();
dept.setDeptno(id);
dept.setDname("该ID:" + id + "没有没有对应的信息,null--@HystrixCommand");
dept.setDb_source("no this database in MySQL");
return dept;
}
}
启动类:
@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
@EnableDiscoveryClient //服务发现
@EnableCircuitBreaker//对hystrixR熔断机制的支持
public class DeptProvider8001_Hystrix_App {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001_Hystrix_App.class, args);
}
}
2.服务降级
当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值
service层:
//@FeignClient(value = "MICROSERVICECLOUD-DEPT")
@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);
}
@Component// 不要忘记添加,不要忘记添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService>{
@Override
public DeptClientService create(Throwable arg0) {
// TODO Auto-generated method stub
return new DeptClientService() {
@Override
public Dept get(long id) {
Dept dept = new Dept();
dept.setDeptno(id);
dept.setDname("该ID:" + id + "没有没有对应的信息,Consumer客户端提供的降级信息,此刻服务Provider已经关闭");
dept.setDb_source("no this database in MySQL");
return dept;
}
@Override
public List<Dept> list() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean add(Dept dept) {
// TODO Auto-generated method stub
return false;
}
};
}
}