Spring Cloud(Finchley版本)系列教程(四) 断路器(Hystrix)
为了更好的浏览体验,欢迎光顾勤奋的凯尔森同学个人博客http://www.huerpu.cc:7000
一、断路器Hystrix
hystrix
是Netlifx
开源的一款容错框架,防雪崩利器,具备服务降级,服务熔断,依赖隔离,监控(Hystrix Dashboard)等功能。hystrix是一个库,通过延迟容忍和容错逻辑,控制分布式服务之间的交互。它通过隔离服务间的访问点、防止级联失败和提供回退选项,保证系统的整体弹性。
二、在Ribbon中使用断路器
复制eurekaClientConsumer
项目,重命名为hepServiceRibbonHystrix
,修改artifactId
、name
、description
为hepServiceRibbonHystrix
,并增加hystrix
依赖。
<artifactId>hepServiceRibbonHystrix</artifactId>
<name>hepServiceRibbonHystrix</name>
<description>hepServiceRibbonHystrix</description>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
修改EurekaClientConsumerApplication
启动类为HepServiceRibbonHystrix
,并在程序的启动类HepServiceRibbonHystrix
加@EnableHystrix
注解开启Hystrix
。
package cc.huerpu.eurekaserver;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class HepServiceRibbonHystrix {
public static void main(String[] args) {
SpringApplication.run(HepServiceRibbonHystrix.class, args);
}
@Bean
public IRule ribbonRule() {
// 负载均衡规则,改为随机
return new RandomRule();
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
修改原来ConsumerController
类中的消费接口,增加@HystrixCommand
注解,并指定回调方法
@RequestMapping("/consumerEurekaClient")
@HystrixCommand(fallbackMethod = "consumerEurekaClientErrorHandler")
public String consumerEurekaClient(){
String res = restTemplate.getForObject("http://eurekaClient/getUserById",String.class);
System.out.println(res);
return "consumerEurekaClient:" + res;
}
public String consumerEurekaClientErrorHandler() {
return "consumerEurekaClientErrorHandler:sorry,EurekaClient cannot handle this request,please try later!";
}
修改项目端口号为8005。
浏览器访问http://localhost:8005/consumerEurekaClient
,此时http://eurekaClient/getUserById
接口是停掉的,也就成功返回了consumerEurekaClientErrorHandler
回调函数的字符串。
三、在OpenFeign中使用断路器
复制项目hepServiceOpenFeign
,重命名为hepServiceOpenFeignHystrix
,修改artifactId
、name
、description
为hepServiceOpenFeignHystrix
<artifactId>hepServiceOpenFeignHystrix</artifactId>
<name>hepServiceOpenFeignHystrix</name>
<description>hepServiceOpenFeignHystrix</description>
<!-- 并增加web依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
修改项目名称为HepServiceOpenFeignHystrixApplication。
package cc.huerpu.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class HepServiceOpenFeignHystrixApplication {
public static void main(String[] args) {
SpringApplication.run(HepServiceOpenFeignHystrixApplication.class, args);
}
}
在UserService
接口上增加fallback = OpenFeignHytrix.class
,OpenFeignHytrix
实现UserService
接口,用于处理调用失败的回调。
package cc.huerpu.eurekaserver.feign;
import cc.huerpu.eurekaserver.config.OpenFeignConfig;
import cc.huerpu.eurekaserver.config.OpenFeignHytrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "eurekaClient",configuration = OpenFeignConfig.class,fallback = OpenFeignHytrix.class)
public interface UserService {
@RequestMapping(value = "/getUserById")
String getUserById();
}
定义一个OpenFeignHytrix
,实现UserService
,并让它注入到容器中。
package cc.huerpu.eurekaserver.config;
import cc.huerpu.eurekaserver.feign.UserService;
import org.springframework.stereotype.Component;
@Component
public class OpenFeignHytrix implements UserService {
@Override
public String getUserById(){
return "Sorry call getUserById interface error, OpenFeignHytrix recommend you try later " ;
}
}
在配置文件中打开hystrix
feign:
hystrix:
enabled: true
修改项目端口号为8009,重启项目,调用http://localhost:8009/getUserByIdFeign
,此时只启动了HepServiceOpenFeignHystrixApplication
一个项目,其余项目都没运行,因此触发了Hystrix
熔断
四、整合Dashboard查看监控数据
在项目hepServiceRibbonHystrix
中添加hystrix-dashboar
依赖 ,并确保有actuator
健康检查依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在启动类上增加@EnableHystrixDashboard
注解。
package cc.huerpu.eurekaserver;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableHystrixDashboard
public class HepServiceRibbonHystrix {
public static void main(String[] args) {
SpringApplication.run(HepServiceRibbonHystrix.class, args);
}
@Bean
public IRule ribbonRule() {
// 负载均衡规则,改为随机
return new RandomRule();
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
首先调用一下http://localhost:8005/consumerEurekaClient
,然后调用http://localhost:8005/actuator/hystrix.stream
,可以看到ping的信息
输入http://localhost:8005/hystrix/
,把刚刚的地址http://localhost:8005/actuator/hystrix.stream
贴进来。
点击进去,可以看到dashboard
信息了