Hystrix熔断
Posted zou-rong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hystrix熔断相关的知识,希望对你有一定的参考价值。
为了避免微服务中因为启动某一个服务宕机,而导致“雪崩”,使整个应用阻塞;
熔断器Hystrix使用了线程隔离和服务降级的方式,提高整体应用的容错能力。
我使用的SpringCloud版本是Hoxton.SR3
线程隔离:Hystrix使用自己的线程池,和主应用服务器线程隔离开来。每个服务都使用独立的线程池。
服务降级:优先保证核心服务可用,非核心服务不可用或若可用。
当某个服务的线程池已满或者响应时间过长,就会响应一个友好提示,而不是无限阻塞或者直接报错。
Hystrix实现了弹性容错,当情况好转之后可以自动重连。
服务消费方:
Eureka-client包已经依赖导入了Hystrix,可以直接使用,无需再导包才怪咧
第一步:导包
上面那个是Eureka-client包中的,不一样。必须导入以下依赖才可以使用@HystrixCommand注解
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
第二步:启动类加注解
package com.company;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
//@EnableDiscoveryClient //启用Eureka客户端
//@SpringBootApplication
//@EnableCircuitBreaker //启用Hystrix熔断功能
@SpringCloudApplication //替代以上三个注解
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
第三步:
@GetMapping("/{id}")
@HystrixCommand(defaultFallback = "getUserByIdFallBack")
public String getUserById(@PathVariable("id")Long id){
String url="http://user-service/user/"+id;
long start=System.currentTimeMillis();
String user = template.getForObject(url, String.class);
long end=System.currentTimeMillis();
log.debug("调用时长:{}",end-start);
return user;
}
public String getUserByIdFallBack(Long id){
return "很抱歉,服务器正忙,请稍后再试。";
}
尽管方法的参数和返回值都一致,还是报了fallback method wasn‘t found: getUserByIdFallBack([])错误,求大佬指教一下。
使用配置当前类降级函数,配置成功
package com.company.controller;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
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")
@Slf4j
@DefaultProperties(defaultFallback = "getUserByIdFallBack")//指定默认降级函数
public class ConsumerController {
@Autowired
private RestTemplate template;
@GetMapping("/{id}")
@HystrixCommand //启用熔断降级
public String getUserById(@PathVariable("id")Long id){
String url="http://user-service/user/"+id;
long start=System.currentTimeMillis();
String user = template.getForObject(url, String.class);
long end=System.currentTimeMillis();
log.debug("调用时长:{}",end-start);
return user;
}
//注意此时的返回值没有限制,不能写参数,因为这是当前类通用的降级方法
public String getUserByIdFallBack(){
return "很抱歉,服务器正忙,请稍后再试。";
}
}
默认调用超时时间为1秒,超过一秒就会触发熔断
服务提供方:
添加休眠模仿超时
package com.company.service.impl;
import com.company.mapper.UserMapper;
import com.company.pojo.User;
import com.company.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
@Service("userService")
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
@Override
public User findOne(Long id) {
try {
TimeUnit.MILLISECONDS.sleep(new Random().nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
return userMapper.selectByPrimaryKey(id);
}
@Override
@Transactional
public void insert(User user) {
user.setUserName("test5");
user.setPassword("test5");
user.setName("ceshi5");
userMapper.insert(user);
// int i=10/0;
}
}
测试结果,调用时长超过1秒的都触发了,低于1秒的都响应成功。
以上是关于Hystrix熔断的主要内容,如果未能解决你的问题,请参考以下文章