说明
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
@EnableHystrix
public class UserConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(UserConsumerApplication .class);
}
// 注册RestTemplate的对象到Spring的容器中
@Bean
@LoadBalanced
public 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个服务器相互调用)
@Autowired
private 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: 8085
spring:
application:
name: user-consumer # 给服务起名称
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10087/eureka
instance:
ip-address: 127.0.0.1 # 配置服务器ip地址
prefer-ip-address: true # 更倾向于使用ip,而不是host名
instance-id: ${eureka.instance.prefer-ip-address}:${server.port} # 自定义实例的id
hystrix:
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: 2000
circuitBreaker:
errorThresholdPercentage: 50 # 触发熔断错误比例阈值,默认值50%
sleepWindowInMilliseconds: 10000 # 熔断后休眠时长,默认值5秒
requestVolumeThreshold: 10 # 触发熔断的最小请求次数,默认20
hystix-demo