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熔断的主要内容,如果未能解决你的问题,请参考以下文章

hystrix 熔断器

Hystrix 熔断

hystrix熔断器之熔断实现

第四篇(续):熔断监控Hystrix Dashboard和熔断聚合监控Hystrix Turbine

Hystrix 熔断器执行和超时实现机制

24.把熔断器整合到我们的客户端代码中(初步)