说明
Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。Hystix 可以解决雪崩问题,Hystix 解决雪崩问题的手段主要是服务降级,包括
- 线程隔离/服务降级
- 服务熔断
服务降级demo
在之前的ribbon-demo例子(SpringCloud_Ribbon.md中有步骤)中,接着做下面的操作
在user-consumer中添加Hystix的依赖
在启动类上开启<!-- Hystrix启动器 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-hystrix</artifactId></dependency>
Hystrix支持@EnableHystrix
编写降级逻辑package com.it.learn;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.netflix.hystrix.EnableHystrix;import org.springframework.context.annotation.Bean;import org.springframework.web.client.RestTemplate;@SpringBootApplication@EnableHystrixpublic class UserConsumerApplication {public static void main(String[] args) {SpringApplication.run(UserConsumerApplication .class);}// 注册RestTemplate的对象到Spring的容器中@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}}
- 编写降级的方法,与原方法返回值,参数列表保持一致
- 在需要降级的方法降级注解,@HystrixCommand(fallbackMethod=”降级方法名”)
package com.it.learn.controller;import com.it.learn.pojo.User;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestController@RequestMapping("consumer")public class UserController {// 发送基于http协议的远程过程调用(2个服务器相互调用)@Autowiredprivate RestTemplate restTemplate;@RequestMapping("/{id}")@HystrixCommand(fallbackMethod = "findUserByIdForFail")public User findUserById(@PathVariable("id") Long id){String url = "http://user-service/user/" + id;// 查询User user = restTemplate.getForObject(url, User.class);return user;}/*** 降级处理的方法,与原方法返回值,参数列表保持一致* @param id* @return*/public User findUserByIdForFail(@PathVariable("id") Long id){User user = new User();user.setId(id);user.setName("网页丢失了");return user;}}
Hystrix默认降级时间为1秒钟,也可以自己配置降级时间
接着,可以重启server:port: 8085spring:application:name: user-consumer # 给服务起名称eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eurekainstance:ip-address: 127.0.0.1 # 配置服务器ip地址prefer-ip-address: true # 更倾向于使用ip,而不是host名instance-id: ${eureka.instance.prefer-ip-address}:${server.port} # 自定义实例的idhystrix:command:default:execution.isolation.thread.timeoutInMilliseconds: 1500 # 单位毫秒logging:level:com.it.learn: debug
user-consumer测试,可以在user-service上打一个断点,故意延时1.5秒后才放行,可以看到服务已降级
服务熔断
1秒发送20个请求,这20个请求都没有拿到预期的响应结果,对着20个请求进行服务降级处理
此时断路器打开,后续再有请求来时,直接进行服务降级
5秒后将断路器设置为中间状态,找一个线程试着去访问,如果访问成功则关闭断路器,服务可以正常运行
如果未能访问成功,则继续打开断路器
熔断器有3种状态
- 熔断器默认为关闭状态: 一切正常
- 中间(半开)状态: 会发送一个请求进行尝试
- 开启状态: 后续所有的请求自动进行服务降级处理(默认5s,进入半开状态),默认请求下访问20次请求,百分之50失败,就开启熔断器
demohystrix:command:default:execution.isolation.thread.timeoutInMilliseconds: 2000circuitBreaker:errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50%sleepWindowInMilliseconds: 10000 # 熔断后休眠时长,默认值5秒requestVolumeThreshold: 10 # 触发熔断的最小请求次数,默认20
hystix-demo
