2.4 熔断器 - 2.4.1. Hystrix
Hystrix
在Spring Cloud中使用了Netflix开发的Hystrix来实现熔断器。下面我们依然通过几个简单的代码示例,进入Hystrix的学习:
通用方式使用Hystrix
代码示例:
新建一个Maven项目,在pom.xml中添加如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice-consumer-movie-ribbon-with-hystrix</artifactId>
<packaging>jar</packaging>
<parent>
<groupId>com.itmuch.cloud</groupId>
<artifactId>spring-cloud-microservice-study</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 整合ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 整合hystrix -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
</dependencies>
</project>
启动类:MovieRibbonHystrixApplication.java,使用@EnableCircuitBreaker注解开启断路器功能:
/**
* 使用@EnableCircuitBreaker注解开启断路器功能
* @author eacdy
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class MovieRibbonHystrixApplication {
/**
* 实例化RestTemplate,通过@LoadBalanced注解开启均衡负载能力.
* @return restTemplate
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(MovieRibbonHystrixApplication.class, args);
}
}
实体类:User.java
public class User {
private Long id;
private String username;
private Integer age;
...
// getters and setters
}
Hystrix业务类:RibbonHystrixService.java,使用@HystrixCommand注解指定当该方法发生异常时调用的方法
@Service
public class RibbonHystrixService {
@Autowired
private RestTemplate restTemplate;
private static final Logger LOGGER = LoggerFactory.getLogger(RibbonHystrixService.class);
/**
* 使用@HystrixCommand注解指定当该方法发生异常时调用的方法
* @param id id
* @return 通过id查询到的用户
*/
@HystrixCommand(fallbackMethod = "fallback")
public User findById(Long id) {
return this.restTemplate.getForObject("http://microservice-provider-user/" + id, User.class);
}
/**
* hystrix fallback方法
* @param id id
* @return 默认的用户
*/
public User fallback(Long id) {
RibbonHystrixService.LOGGER.info("异常发生,进入fallback方法,接收的参数:id = {}", id);
User user = new User();
user.setId(-1L);
user.setUsername("default username");
user.setAge(0);
return user;
}
}
controller:RibbonHystrixController.java
@RestController
public class RibbonHystrixController {
@Autowired
private RibbonHystrixService ribbonHystrixService;
@GetMapping("/ribbon/{id}")
public User findById(@PathVariable Long id) {
return this.ribbonHystrixService.findById(id);
}
}
application.yml
server:
port: 8011
spring:
application:
name: microservice-consumer-movie-ribbon-with-hystrix
eureka:
client:
serviceUrl:
defaultZone: http://discovery:8761/eureka/
instance:
hostname: ribbon # 此处,preferIpAddress不设置或者设为false,不能设为true,否则影响turbine的测试。turbine存在的问题:eureka.instance.hostname一致时只能检测到一个节点,会造成turbine数据不完整
验证:
启动注册中心:microservice-discovery-eureka
启动服务提供方:microservice-provider-user
启动服务消费方:microservice-consumer-movie-ribbon-with-hystrix
访问:http://localhost:8011/ribbon/1,获得结果:
{"id":1,"username":"Tom","age":12}
关闭服务提供方:microservice-provider-user,访问http://localhost:8011/ribbon/1,获得结果:
{"id":-1,"username":"default username","age":0}
,另外日志打印:c.i.c.s.u.service.RibbonHystrixService : 异常发生,进入fallback方法,接收的参数:id = 1
。
注意:
- 本示例代码在microservice-consumer-movie-ribbon基础上修改而来
- 如对本示例涉及的知识点有疑难,请查看上一章《服务消费者》
代码地址(任选其一):
Feign使用Hystrix
代码示例
在Feign中使用Hystrix是非常简单的事情,因为Feign已经集成了Hystrix。我们使用microservice-consumer-movie-feign-with-hystrix项目的代码做一点修改,将其中的UserClient.java修改为如下即可:
/**
* 使用@FeignClient注解的fallback属性,指定fallback类
* @author eacdy
*/
@FeignClient(name = "microservice-provider-user", fallback = HystrixClientFallback.class)
public interface UserFeignHystrixClient {
@RequestMapping("/{id}")
public User findByIdFeign(@RequestParam("id") Long id);
/**
* 这边采取了和Spring Cloud官方文档相同的做法,将fallback类作为内部类放入Feign的接口中,当然也可以单独写一个fallback类。
* @author eacdy
*/
@Component
static class HystrixClientFallback implements UserFeignHystrixClient {
private static final Logger LOGGER = LoggerFactory.getLogger(HystrixClientFallback.class);
/**
* hystrix fallback方法
* @param id id
* @return 默认的用户
*/
@Override
public User findByIdFeign(Long id) {
HystrixClientFallback.LOGGER.info("异常发生,进入fallback方法,接收的参数:id = {}", id);
User user = new User();
user.setId(-1L);
user.setUsername("default username");
user.setAge(0);
return user;
}
}
}
这样就完成了,是不是很简单呢?测试过程类似通用方式。
注意:
- 本示例代码在microservice-consumer-movie-feign基础上修改而来
- 如对本示例涉及的知识点有疑难,请查看上一章《服务消费者》