主要是为了解决服务的雪崩问题,即一个服务出错,引起多个相关的服务无法正常运行。
1、导入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
2、在启动类上添加注解
@EnableCircuitBreaker
3、针对接口编写降级方法
//降级方法,可自定义
public Customer findByIdFallback(Integer id) {
return new Customer(-1,"",0);
}
@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback")
public Customer findById(@PathVariable(value = "id") Integer id) {
int i = 1 / 0;
return searchClient.findById(id);
}
4、在被调用的方法上添加注解
@HystrixCommand(fallbackMethod = "findByIdFallback")
如果使用服务的线程池取接收用户的请求,并使用当前线程去执行调用其他服务的功能,如果其他服务出现了故障,导致该服务的线程大量堆积,导致该服务无法处理其他业务的功能。
1、Hystrix的线程池(默认的配置),接收用户请求时,会使用服务的线程池,执行业务代码,调用其他服务时,采用Hystrix的线程池。
2、信号量,使用的还是服务的线程池,但是能够帮助管理线程池,避免线程大量堆积,无法处理新请求的问题。
具体的配置name属性需要去查看HystrixCommandProperties类
1、线程隔离的策略:
name=hystrix.command.default.execution.isolation.strateg
, value=THREAD, SEMAPHORE
2、指定超时时间(只针对线程池):name=hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
, value=1000
3、是否开启超时时间配置:
name=hystrix.command.default.execution.timeout.enable
, value=true
4、超时之后是否中断线程:name=hystrix.command.default.execution.isolation.thread.interruptOnTimeout
, value=true
5、取消之后是否中断:
name=hystrix.command.default.execution.isolation.thread.interruptOnCancel
, value=false
1、指定信号量的最大并发请求书
name=hystrix.command.default.execution.isolation.semaphore.maxConcurrenRequests
, value=10
2、线程隔离的策略:
name=hystrix.command.default.execution.isolation.strateg
, value=THREAD, SEMAPHORE
在调用指定服务时,如果失败率达到了输入的一个阈值,将断路器从Closed的状态转变为Open状态。此时指定服务无法被访问,如果被访问,会执行fallback方法。在一定时间内,会再次转变为half open状态,允许一个请求发送到我的指定服务,如果成功,转变为closed,如果失败,服务会再次转变为open状态,会再次循环上述过程,直到变为closed状态。
配置断路器的监控界面
1、导入依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
dependency>
2、在启动类添加注解
@EnableHystrixDashboard
3、配置一个servlet路径,指定上Hystrix的servlet
@WebServlet("/hystrix.stream")
public class HystrixServlet extends HystrixMetricsStreamServlet {
}
//在启动类上,添加扫描Servlet的注解
@ServletComponentScan("com.arivan.servlet")
5、使用
直接访问映射好的Servlet的路径
配置断路器的属性
1、断路器的开关:name=hystrix.command.default.circuitBreaker.enable
, value=true
2、失败阈值的总请求数:
name=hystrix.command.default.circuitBreaker.requestVolumeThreshold
, value=20
3、请求总数失败率:
name=hystrix.command.default.circuitBreaker.errorThresholdPercentage
, value=50
4、断路器open状态后,多少秒是拒绝请求的:
name=hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds
, value=5000
5、强制让服务拒绝请求:
name=hystrix.command.default.circuitBreaker.forceOpen
, value=false
6、强制服务接收请求(与5互斥):
name=hystrix.command.default.circuitBreaker.forceClose
, value=false
具体配置:
@GetMapping("/customer/{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback", commandProperties = {
@HystrixProperty(name = "execution.isolation.strategy",value = "SEMAPHORE"),
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
})
1、请求缓存的生命周期是一次请求。
2、请求缓存时缓存当前线程中的一个方法,将方法的返回结果作为value。
3、在一次请求中,目标方法被调用过一次以后,都会被缓存。
请求缓存的实现
1、创建一个service,并在service中调用search服务
@Service
public class CustomerService {
@Autowired
private SearchClient searchClient;
@CacheResult
@HystrixCommand(commandKey = "findById")
public Customer findById(@CacheKey Integer id) throws InterruptedException {
return searchClient.findById(id);
}
@CacheRemove(commandKey = "findById")
@HystrixCommand
public void clearFindById(@CacheKey Integer id) {
System.out.println("findById缓存被清空");
}
}
2、使用请求缓存的注解
@CacheResult //帮助缓存当前方法的返回结果(需要和@HystrixCommand配合使用)
@CacheRemove //帮助清除某一个缓存信息(基于CommandKey)
@CacheKey //指定方法中的哪个参数作为缓存的key
3、编写Filter,去构建HystrixRequestContext
@WebFilter("/*")
public class HystrixRequestContextInitFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HystrixRequestContext.initializeContext();
filterChain.doFilter(servletRequest,servletResponse);
}
}
//需要在启动类上添加注解,使该Filter能够被扫描到
@ServletComponentScan({"com.arivan.servlet","com.arivan.filter"})