当服务的某个 API 接口的失败次数在一定时间内小于设定的阈值时,熔断器处于关闭状态,该 API 接口正常提供服务。当该 API 接口处理请求的失败次数在一定时间内大于设定的阈值时,Hystrix 判定该 API 接口出现了故障,打开熔断器,这时该 API 接口会执行快速失败的逻辑,不执行业务逻辑,请求的线程不会阻塞。处于打开状态的熔断器,一段时间后会处于半打开状态,并将一定数量的请求执行正常逻辑,剩余的请求会执行快速失败。若执行正常逻辑的请求失败了,则熔断器继续打开;若成功了,则熔断器关闭。这样熔断器就具有了自我修复的能力。
在 RestTemplate 和 Ribbon 上使用熔断器
本例采用 Maven 多模块结构,其中 eureka-server、service-provider、service-consumer 的代码和使用 RestTemplate 和 Ribbon 消费服务中的类似,这里只展示需要修改的地方。
首先在 service-consumer 的 pom 文件中加入 hystrix 的依赖,修改后的 pom 文件如下:
<?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>service-consumer</artifactId>
<parent>
<artifactId>spring-cloud-resttemplate-hystrix</artifactId>
<groupId>com.wuychn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
然后在启动类 ServiceConsumerApplication 上加上 @EnableHystrix 注解,开启 Hyxtrix 熔断器功能:
package com.wuychn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class ServiceConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceConsumerApplication.class, args);
}
}
修改 HiService,在 hi() 方法上加上 @HystrixCommand 注解,其 fallbackMethod 属性指定回退逻辑执行的方法,有了该注解,hi() 方法就启用了 Hystrix 熔断器的功能:
package com.wuychn.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class HiService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hi(String name) {
return restTemplate.getForObject("http://service-provider/hi?name=" + name, String.class);
}
public String hiError(String name) {
return "sorry, " + name + ", please wait..";
}
}
依次启动 eureka-server、service-provider 和 和 service-consumer,在浏览器中访问 http://localhost:9004/hi,可以正常返回结果。之后关闭 service-provider 服务,再次访问 http://localhost:9004/hi,可以看到如下的输出:
sorry, wuychn, please wait..
由此可见,当服务提供者的 API 接口不可用时,熔断器会被打开,之后请求该接口的方法会执行快速失败,进入 fallbackMethod 指定的逻辑。
在 Feign 上使用熔断器
本例采用 Maven 多模块结构,其中,eureka-server、service-provider、service-consumer 的代码和使用 Feign 消费服务中的类似,这里只展示需要修改的地方。
由于 Feign 的起步依赖中已经加入了 Hystrix 的依赖,所以在 Feign 中使用 Hystrix 不需要加入任何其他依赖,只需在 service-consumer 的 application.yml 中配置开启 Hystrix 的功能:
spring:
application:
name: service-consumer
server:
port: 9004
eureka:
client:
serviceUrl:
defaultZone: http://localhost:9001/eureka/
feign:
hystrix:
enabled: true
然后修改 service-consumer 的 HiFeignClient 接口,在 @FeignClient 注解的 fallback 属性上配置快速失败的处理类,该处理类必须实现 @FeignClient 修饰的接口,并且需要加上 @Component 注解将其注入到 IoC 容器中,修改后的 HiFeignClient 如下:
package com.wuychn.client;
import com.wuychn.client.config.FeignConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "service-provider", configuration = FeignConfig.class, fallback = HiFeignFallback.class)
public interface HiFeignClient {
// 如果不添加@RequestParam注解,会被转化为POST请求,从而报405
@GetMapping("/hi")
String hi(@RequestParam(value = "name") String name);
}
@Component
class HiFeignFallback implements HiFeignClient {
@Override
public String hi(String name) {
return "sorry, " + name + ", please wait..";
}
}
依次启动 eureka-server、service-provider 和 和 service-consumer,在浏览器中访问 http://localhost:9004/hi,可以正常返回结果。之后关闭 service-provider 服务,再次访问 http://localhost:9004/hi,可以看到如下的输出:
sorry, wuychn, please wait..
说明在 Feign 中已经成功加入了 Hystrix 熔断器的功能。