Hystrix
Hystrix是什么?
Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix能够在一个依赖出问题的情况下,
不会导致整体的失败,避免联级故障,以提高分布式系统的弹性
断路器
断路器 本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似于保险丝)向调用方返回一个符合预期的可处理的备选响应(FallBack)而不长时间的等待
或者抛出一个调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间,不必要地占用,从而避免故障在分布式系统中的蔓延,乃至雪崩。
服务熔断
熔断机制是应对雪崩效应的一种微服务链路保护机制
、当扇出的链路的某个微服务不可用或响应时间太长时,会进行服务的降级,进而熔断该节点的微服务的调用,快速返回错误的响应信息 当检测到该节点微服务调用响应正常后恢复调用链路
。在SpringCloud框架熔断机制通过Hystrix实现。Hystrix会监控微服务间的调用状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制,熔断机制是注解
@HystrixCommand.
超时机制
通过网络请求其他服务时,都必须设置超时,征程情况下,一个远程调用一般在几十毫秒被就返回了,
当依赖的服务不可用或者因为网络问题,响应时间将会变的很长,而通常情况下,一次远程调用对应了一个线程,
如果响应太慢,那么这个线程得不到释放,而线程对应了系统资源,如果大量的线程得不到释放,并且越积越多.
服务资源就会被耗尽,从而导致资源服务不可用,所以必须为每个请求设置超时时间,如果超时,则释放线程资源.
实现断路器的思路
1.监控 监控总共请求多少次,有多少次失败,假设失败率为多少,断路器打开
2.状态 打开,关闭,断开
3.分流
4.自我修复(状态的切换)
方法级
第一步导入依赖pom.xml
<
dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix
public class LearnerApplication {
public static void main(String[] args) {
SpringApplication.run(LearnerApplication.class,args);
}
}
方法级容错回调
//获取考试试卷试题列表(用于学生讲解,带答案)
@RequestMapping(value = "/getAnswerQuestionStudentList",method = RequestMethod.POST,name = "PROFILE")
@HystrixCommand(fallbackMethod = "getAnswerQuestionStudentListFallBack",commandProperties = {
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ENABLED,value = "true"), //开启熔断
@HystrixProperty(name = HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value = "SEMAPHORE"), //隔离策略: 线程模式,信号量模式
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD,value="1"),//请求数量达到10个后才计算
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE,value = "1"),//错误率
@HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "1000")//当满足请求数量和 错误率后,会在这个时间内随机拿取一个请求查看是否成功,成功则正常运行,否则继续运行该后备方法
})
public Result getAnswerQuestionStudentList(@RequestBody Exam exam){
return studentExamService.getAnswerQuestionStudentList(exam);
}
public Result getAnswerQuestionStudentListFallBack(Exam exam){
return new Result(ResultCode.FAIL,"请求错误,服务调用失败,启用后备方法");
}
Hystrix的隔离策略两种: 分别是线程隔离和信号量隔离。
THREAD(线程隔离):使用该方式,HystrixCommand将会在单独的线程上执行,并发请求受线程池中线程数量的限制。
SEMAPHORE(信号量隔离):使用该方式,HystrixCommand将会在调用线程上执行,开销相对较小,并发请求受到信号量个数的限制。
Hystrix中默认并且推荐使用线程隔离(THREAD),因为这种方式有一个除网络超时以外的额外保护。
一般来说,只有当调用负载异常高时(例如每个实例每秒调用数百次)才需要信号量隔离,因为这种场景下使用THREAD开销会比较高。信号量隔离一般仅适用于非网络调用的隔离。
可以使用execution.isolation.strategy属性指定隔离策略。
正常情况下,默认为线程隔离, 保持默认即可。
如果发生找不到上下文运行时异常,可考虑将隔离策略设置为SEMAPHORE
Feign的回调
application.yml
feign:
client:
config:
default:
connectTimeout: 50000
readTimeout: 50000
loggerLevel: full
hystrix:
enabled: true
``
创建UserClientFallback
@Component
public class UserClientFallback implements UserClient {
//省略其他接口实现....
@Override
public Result getQuestionExamTeacherList(Exam exam) {
return new Result(ResultCode.FAIL,"启动了userClient实现类的后备方法");
}
}
UserClient
@FeignClient(name = “JWXT-TEACHER”,fallback = UserClientFallback=.class)
public interface UserClient {
//do something …
}
Feign回调工厂
application.yml
#配置断路器
# 配置断路器
hystrix:
command:
default:
circuitBreaker:
enabled: true #启动断路器
requestVolumeThreshold: 10 #请求数达到后才计算
sleepWindowInMilliseconds: 10000 #休眠时间
errorThresholdPercentage: 50 #错误率
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 #设置请求超时时间(默认是一秒) 超时后会走后备方法
.UserClientFallbackFactory
package com.jwxt.clients.fallback;
import com.jwxt.clients.UserClient;
import com.jwxt.entity.academic.Exam;
import com.jwxt.response.Result;
import com.jwxt.response.ResultCode;
import com.jwxt.vo.QuestionVo;
import feign.hystrix.FallbackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class UserClientFallbackFactory implements FallbackFactory {
private static final Logger LOGGER = LoggerFactory.getLogger(UserClientFallbackFactory.class);
@Override
public UserClient create(Throwable e) {
LOGGER.warn("错误服务回调:{}",e.getMessage());
return new UserClient() {
//省略其他接口实现...
@Override
public Result getQuestionExamTeacherList(Exam exam) {
return new Result(ResultCode.FAIL,"启动了回调工厂");
}
};
}
}
@FeignClient(name = “JWXT-TEACHER”,fallbackFactory = UserClientFallbackFactory.class)
public interface UserClient {
//do something …
}
禁用Feign的Hystrix
方式一:
application.yml
feign.hystrix.enabled=false
方式二:
通过代码的方式禁用某个客户端
@Configuration
public class FeignConfiguration {
@Bean
@Scope(“prototype”)
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}