所谓的熔断机制和日常生活中见到电路保险丝是非常相似的,当出现了问题之后,保险丝会自动烧断,以保护我们的电器, 那么如果换到了程序之中呢?
当现在服务的提供方出现了问题之后整个的程序将出现错误的信息显示,而这个时候如果不想出现这样的错误信息,而希望替换为一个错误时的内容。
一个服务变慢了,后续的其他调用者服务跟着不能用了,这就是雪崩效应
对于熔断技术的实现需要考虑以下几种情况:
· 出现错误之后可以 fallback 错误的处理信息;
· 如果要结合 Feign 一起使用的时候还需要在 Feign(客户端)进行熔断的配置。
一、基于ribbon的Hystrix 基本配置
1、复制项目重命名为springcloud-moveServer-hystrix修改调用方 pom.xml 配置文件,追加 Hystrix 配置类:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2.修改程序 controller
package com.pupeiyuan.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.pupeiyuan.bean.NhReportStatusHistory;
@RestController
@RefreshScope
public class ConfigClientController {
//spring 提供用于访问rest接口的模板对象
@Autowired
@Qualifier(value = "remoteRestTemplate")
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "findByIdFallback")
@GetMapping("/balance/{id}")
public List<NhReportStatusHistory> getBalance(@PathVariable Long id) {
return this.restTemplate.getForObject("http://MULTIPLE/getDate/"+id, List.class);
}
public List<NhReportStatusHistory> findByIdFallback(Long id) {
NhReportStatusHistory nhreportstatushistory = new NhReportStatusHistory();
nhreportstatushistory.setId("000000000000");
List<NhReportStatusHistory> list = new ArrayList<>();
list.add(nhreportstatushistory);
return list;
}
}
这里需要注意的是,fallback方法的参数和类型要和原方法保持一致,否则会出现异常
3、在主类之中启动熔断处理
package com.pupeiyuan.config;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.support.SpringBootServletInitializer;
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.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.web.client.RestTemplate;
import feign.Logger;
@Configuration
//扫描bean
@ComponentScan(basePackages = "com.pupeiyuan.*")
//不用自动配置数据源
@EnableDiscoveryClient
@SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
@EnableFeignClients(basePackages="com.pupeiyuan.feignClient")
@EnableCircuitBreaker
public class MainApplication extends SpringBootServletInitializer {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
//相当于xml中的bean标签 用于调用当前方法获取到指定的对象
@Bean(name="remoteRestTemplate")
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(MainApplication.class);
}
}
到此,一个简单基于ribbon的Hystix熔断机制就配置好了。
二、基于Feign client的Hystrix 配置
1、复制项目重命名为springcloud-moveServer-hystrix修改调用方 pom.xml 配置文件,追加 Hystrix 配置类:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2、增加配置启用
feign.hystrix.enabled=true
3、启动类增加注解
@EnableCircuitBreaker
4、增加FeignClient2业务接口,并配置fallback
package com.pupeiyuan.feignClient;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.config.FeignConfiguration;
import com.pupeiyuan.bean.NhReportStatusHistory;
import feign.Param;
import feign.RequestLine;
@FeignClient(name = "MULTIPLE",configuration = FeignConfiguration.class,fallback=HystrixClientFallback.class)
public interface FeignClient2 {
@RequestMapping(value = "/getDate/{id}", method = RequestMethod.GET)
public List<NhReportStatusHistory> dataList(@PathVariable("id") Long id);
}
5.增加HystrixClientFallback类
package com.pupeiyuan.feignClient;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Component;
import com.pupeiyuan.bean.NhReportStatusHistory;
@Component
public class HystrixClientFallback implements FeignClient2{
@Override
public List<NhReportStatusHistory> dataList(Long id) {
NhReportStatusHistory nhreportstatushistory = new NhReportStatusHistory();
nhreportstatushistory.setId("99999999999999");
List<NhReportStatusHistory> list = new ArrayList<>();
list.add(nhreportstatushistory);
return list;
}
}
演示如下,停调multiple服务,请求结果
请求健康状态接口显示断路器已经在打开状态
三、如何禁用单个FegionClient的Hystrix的支持
在自定义Feign Client配置文件FeignConfiguration.java中新增配置即可
package com.pupeiyuan.feignClientConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import feign.Contract;
import feign.Feign;
import feign.Logger;
@Configuration
public class FeignConfiguration {
@Bean
public Contract feignContract() {
//这里可以配置默认配置
return new feign.Contract.Default();
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder();
}
}
使用这个feign client配置文件的feign client都不会启用熔断器
四、Feign使用fallbackFactory属性打印fallback异常
1、基本配置略
2、配置UserFeignClient
@FeignClient(name = "microservice-provider-user", fallbackFactory = HystrixClientFallbackFactory.class)
public interface UserFeignClient {
// @GetMapping("/sample/{id}")
@RequestMapping(method = RequestMethod.GET, value = "/sample/{id}")
public User findById(@PathVariable("id") Long id);
}
注意:配置了fallbackFactory ,如果同时设置fallback和fallbackfactory不可以有冲突,只能设置一个,fallbackFactory 是fallback的一个升级版
3、fallbackFactory 的类设置HystrixClientFallbackFactory
@Component
public class HystrixClientFallbackFactory implements FallbackFactory<UserFeignClient> {
private static final Logger logger = LoggerFactory.getLogger(HystrixClientFallbackFactory.class);
@Override
public UserFeignClient create(Throwable arg0) {
HystrixClientFallbackFactory.logger.info("fallback reason was:{}", arg0.getMessage());
return new UserFeignClientWithFactory() {
@Override
public User findById(Long id) {
User user = new User();
user.setId(-1L);
return user;
}
};
}
}
4、UserFeignClientWithFactory设置
public interface UserFeignClientWithFactory extends UserFeignClient {
}