1. Hystrix
1.1 简介
Hystix,即熔断器。
主页:https://github.com/Netflix/Hystrix/
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。
使用熔断器Hystrix为了优化项目。
1.2 熔断器的工作机制:
正常工作的情况下,客户端请求调用服务API接口:
当有服务出现异常时,直接进行失败回滚,00000000处理:
当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。
这就好比去买鱼,平常超市买鱼会额外赠送杀鱼的服务。等到逢年过节,超时繁忙时,可能就不提供杀鱼服务了,这就是服务的降级。
系统特别繁忙时,一些次要服务暂时中断,优先保证主要服务的畅通,一切资源优先让给主要服务来使用,在双十一、618时,京东天猫都会采用这样的策略。
1.3 动手实践
1.3.1 引入依赖
首先在eureka_client中引入Hystrix依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1.3.2 开启熔断
/**
* Created by liangtong.
*/
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //开启熔断器
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class,args);
}
}
1.3.3 改造调用方
我们改造eureka_client,修改DataDao的data方法,并且声明一个失败时的回滚处理函数dataFallback:
@Component
public class DataDao {
@Resource
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "dataFallback",commandProperties = @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000"))
public ResponseEntity<String> data(){
long start = System.currentTimeMillis();
ResponseEntity<String> entity = restTemplate.getForEntity("http://service/test", String.class);
long end = System.currentTimeMillis();
System.out.println("访问用时:" + (end-start));
return entity;
}
public ResponseEntity<String> dataFallback(){
return ResponseEntity.ok("临时数据");
}
}
• @HystrixCommand(fallbackMethod=“dataFallback”):声明一个失败回滚处理函数dataFallback,当data执行超时(默认是1000毫秒),就会执行fallback函数,返回替代内容。
• 为了方便查看熔断的触发时机,我们记录请求访问时间。
• 多学一招:通过@HystrixCommand的commandProperties 可以设置默认时间
// HystrixCommandProperties Hystrix命令参数配置类
@HystrixCommand(fallbackMethod = "dataFallback",commandProperties = @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000"))
1.3.4 改造服务提供者
改造服务提供者eureka_service,随机休眠一段时间,以触发熔断:
/**
* Created by liangtong.
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping
public ResponseEntity<String> test(HttpServletRequest request) throws InterruptedException {
Thread.sleep(new Random().nextInt(2000));
return ResponseEntity.ok("测试数据" + request.getServerPort());
}
}
1.3.6 面试题
如果熔断和重试机制,都配置,是都生效?还是某个生效?
经测试发现是熔断生效,为什么?
\1. Ribbon重试机制的超时时间设置的是1000ms:
2.Hystix的超时时间默认也是1000ms
3.实际执行后发现,没有触发重试机制,而是先触发了熔断。
l 所以,Ribbon的超时时间一定要小于Hystix的超时时间。
我们可以通过hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds来设置Hystrix超时时间。
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 设置hystrix的超时时间为3000ms
ix超时时间。
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 设置hystrix的超时时间为3000ms