所謂的熔斷機制和日常生活中見到電路保險絲是非常相似的,當出現了問題之后,保險絲會自動燒斷,以保護我們的電器, 那么如果換到了程序之中呢?
當現在服務的提供方出現了問題之后整個的程序將出現錯誤的信息顯示,而這個時候如果不想出現這樣的錯誤信息,而希望替換為一個錯誤時的內容。
一個服務掛了后續的服務跟着不能用了,這就是雪崩效應
對於熔斷技術的實現需要考慮以下幾種情況:
· 出現錯誤之后可以 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 {
}