什么是雪崩效应
在微服务架构中通常会有多个服务层调用,基础服务的故障可能会导致级联故障,进而造成整个系统不可用的情况,这种现象被称为服务雪崩效应。服务雪崩效应是一种因“服务提供者”的不可用导致“服务消费者”的不可用,并将不可用逐渐放大的过程。如果下图所示:A作为服务提供者,B为A的服务消费者,C和D是B的服务消费者。A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
什么是Hystrix
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖(服务)不可避免的会调用失败,比如异常、超时等,Hystrix能够保证在一个依赖(服务)出现问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式的弹性。
“断路器”(CircuitBreaker)本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个服务预期的,可处理的备选响应(callBack),而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务的 现场不会被长时间、不必要的占用,从而避免了故障在分布式系统中的蔓延。
个人理解:熔断是在接口提供方进行熔断处理,当某个接口处理事件过长或者异常的情况下,返回一个备选响应。这是和服务降级最大的一个区别。
Hystrix能做什么
1. 服务降级
2. 服务熔断
3. 服务限流
4. 接近实时的监控
服务熔断
一般是某个服务故障或者是异常引起的。熔断机制是应对雪崩效应的一种微服务链路保户机制,当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的相应信息。当检测当该节点微服务调用响应正常后恢复调用链路,熔断的目的是当A服务模块中的某块程序出现故障后为了不影响其他客户端的请求而做出的及时回应。
在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定的阈值,缺省是5秒内20次调用失败就会启动熔断机制。熔断机制的注解是@HystrixCommand。
服务熔断简单测试demo:
1.首先当然是需要加Hystrix的依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2. 开启服务对熔断的支持
package com.maorui.consul;
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.openfeign.EnableFeignClients;
/**
* @Author
* @Description TODO
* @Date 2021:04:21 23:16
*/
@SpringBootApplication
@EnableDiscoveryClient//服务发现
@EnableFeignClients
@EnableCircuitBreaker//添加对熔断的支持
public class ServiceProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceProviderApplication.class);
}
}
在application.properties中开启hystrix的开关
feign.hystrix.enabled=true
3.熔断配置
package com.maorui.consul.controller;
import com.maorui.consul.entity.Product;
import com.maorui.consul.service.ProductService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
/**
* @Author
* @Description TODO
* @Date 2021:04:26 23:16
*/
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/list")
//fallbackMethod是发生错误时调用的方法
@HystrixCommand(fallbackMethod = "hystrixSimpleTest")
public List<Product> selectProductList(Integer id){
//id不等于1,2,3时会抛出异常
List<Product> productList = productService.selectProductList(id);
if (productList == null){
throw new RuntimeException("运行时异常!!!");
}
return productList;
}
private List<Product> hystrixSimpleTest(Integer id){
List<Product> productList = new ArrayList<>();
productList.add(new Product(1, "熔断测试产品", 1, 250D));
return productList;
}
}
4.测试结果
@HystrixCommand注解说明:
public @interface HystrixCommand {
// HystrixCommand 命令所属的组的名称:默认注解方法类的名称
String groupKey() default "";
// HystrixCommand 命令的key值,默认值为注解方法的名称
String commandKey() default "";
// 线程池名称,默认定义为groupKey
String threadPoolKey() default "";
// 定义回退方法的名称, 此方法必须和hystrix的执行方法在相同类中
String fallbackMethod() default "";
// 配置hystrix命令的参数
HystrixProperty[] commandProperties() default {};
// 配置hystrix依赖的线程池的参数
HystrixProperty[] threadPoolProperties() default {};
// 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。我们也可以通过此方法定义哪些需要忽略的异常
Class<? extends Throwable>[] ignoreExceptions() default {};
// 定义执行hystrix observable的命令的模式,类型详细见ObservableExecutionMode
ObservableExecutionMode observableExecutionMode() default ObservableExecutionMode.EAGER;
// 如果hystrix方法抛出的异常包括RUNTIME_EXCEPTION,则会被封装HystrixRuntimeException异常。此方法定义需要抛出的异常
HystrixException[] raiseHystrixExceptions() default {};
// 定义回调方法:但是defaultFallback不能传入参数,返回参数和hystrix的命令兼容
String defaultFallback() default "";
}
服务降级:
服务器当压力剧增的时候,根据当前业务情况及流量,对一些服务和页面进行有策略的降级。
服务降级处理是在客户端实现完成的,与服务端没有关系。整体资源快不够了,忍痛将某些服务单元先关掉,关闭后还要返回一些可处理的备选方法,待渡过难关,再开启回来。
服务降级简单测试demo(http://www.bubuko.com/infodetail-3286046.html):
1. 首先需要创建一个降级服务,并实现FallbackFactory接口,且泛型为Feign的调用接口。
@Component
public class UserClientService implements FallbackFactory<UserService> { //Feign调用的接口
@Override
public UserService create(Throwable throwable) {
//构建匿名
return new UserService() {
@Override
public User findById(Integer id) {
return new User(id,"该ID:"+id+"没有对应的数据","Hystrix此服务以关闭");
}
@Override
public List<User> findAll() {
return null;
}
};
}
}
2. Feign的封装接口层调用fallbackFactory的实现类
@FeignClient(value = "MICROSERVICE-PRODUCT",fallbackFactory = UserClientService.class) //指明服务关闭后,会返回方法的类的字节码
public interface UserService {
@GetMapping("/product/findone/{id}")
public User findById(@PathVariable("id") Integer id);
@GetMapping("/product/list")
public List<User> findAll();
}
3.测试。
当我们的整体资源不快够用,需要关闭该服务,又不想整体资源因依赖这个服务而发生级联效应,我们使用了上面的技术进行了服务降级处理,当我们关闭此服务后:
总结:
服务雪崩:当A调用微服务B,B调C,和其他微服务,这是扇出,当扇出链路上某个微服务调用响应时间过长或者不可用,对微服务的A的调用就会占用越来越多的系统资源,导致系统崩溃,所谓的雪崩效应
服务熔断:一般是某个服务异常引起的,相当于“保险丝”,当某个异常条件被触发,直接熔断整个服务,不是等到此服务超时
服务降级:降级一般是从整体负荷考虑,当某个服务熔断之后,服务器将不再被调用,客户端可自己准备一个本地的fallback回调,返回一个缺省值,虽然服务水平下降,当能用,比直接挂掉要强
参考文档: