背景: 多个微服务之间调用的时候,假如微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的"扇出"。
如果扇出的链路上某个微服务的调用响应的时间过长或者不可用,对微服A的调用就会占用越来越多的系统资源,进而引起系统崩溃,即"雪崩效应"。
1.1 Hystrix简介
Hystrix作为Netflix公司推出的一款针对分布式系统延迟和容错的开源库,是实现了容错机制的组件,设计的目的是通过添加延迟容忍和容错逻辑,从而控制分布式服务之间的交互。
对于一个复杂的分布式系统,包含的应用可能有数十个,这些应用有许多依赖项目,每个依赖项目不可避免在某个时刻会失败,导致出现故障。如果不对这些故障进行隔离,整个系统就可能会面临崩溃。
1.2 Hystrix具体实现
1.将外部依赖的访问请求封装在独立的线程中,进行资源隔离;
2.对于超出设定阈值的服务调用,直接进行超时处理,不允许其耗费过长时间阻塞线程;
3.每个依赖服务维护一个独立的线程池,一旦线程池满了,直接拒绝服务的调用;
4.统计依赖服务的成功次数,失败次数,拒绝次数,超时次数等结果
5.在一段时间内,如果服务调用的异常次数超过一定的阈值,就会触发熔断器,停止对特定服务的所有请求,在一定时间内对服务调用直接降级,一段时间后自动恢复;
6.如果某个服务出现调用失败,被拒绝,超时等异常情况,就会自动调用fallback降级机制;
7.实时监控指标和配置变化。
1.3Hystrix入门
1 搭建Eureka-server
这里我们无需再去进行Springboot项目eureka-server的搭建,直接使用搭建Eureka所用到的Eureka-server
2 创建Eureka-hystrix-client的SpringBoot项目
使用Spring Initializr的方式创建一个名为demo-hystrix-client的springBoot项目,添加Eureka Client,Web,Feign,Ribbon,Hystrix依赖,
3 启动类添加@EnableHystrix注解,启动熔断功能
在eureka-hystrix-client的启动类中添加@EnableHystrix注解,启动熔断功能
4 创建config包,在包下创建HystrixConfig类
代码如下:
package com.example.demo.hystrix.client.config;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @Title: HystrixConfig
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/5/27 15:42
*/
@Configuration
public class HystrixConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
5 创建controller包,在包下创建类LocalItemController类并增加@RestController注解
package com.example.demo.hystrix.client.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Title: LocalItemController
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/5/27 15:45
*/
@RestController
public class LocalItemController {
@Autowired
LocalItemController localItemController;
@GetMapping("/hi")
public String hi(String id){
return localItemController.hi(id);
}
}
6 新建service包,包下新建LocalItemSerice类,在类中添加注解
package com.example.demo.hystrix.client.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
/**
* @Title: LocalItemService
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/5/27 15:53
*/
@Service
public class LocalItemService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hi(String id){
return restTemplate.getForObject(
"http://hystrix-provider/hi?id="+id,String.class
);
}
public String hiError(String id){
return String.format("hi,your message is:%s but requst bad.",id);
}
}
7 使用Spring Initialzr的方式创建一个名称为hystrix-provider的SpringBoot项目,添加Eureka client,test,web依赖
8.在hystrix-provider中创建controller包。并在包下创建HystrixController类。在类中添加hi()方法
package com.example.hystrixprovider.controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Title: HystrixController
* @Description:
* @Auther:
* @Version: 1.0
* @create 2023/5/27 16:09
*/
public class HystrixController {
@RequestMapping("/hi")
public String hi(String id){
return "Hello world,I'm from hystrix!"+id;
}
}
9. 启动服务并进行测试。
依次启动eureka-server,hystrix-provider,eureka-hystrix-client,在浏览器中输入http://localhost:8764!id=12
浏览器会显示出:
Hello World,I'm from hystrix!12
关闭服务提供者demo-provider,制造服务不可用的情形,再次进行浏览器请求,浏览器会显示:
Hi ,your message is: 12 but request bad.