在使用springcloud搭建為服務架構項目中,我們會根據業務或功能将系統拆分為多個服務單元,各個單元之間通過服務注冊和訂閱的方式互相依賴和調用功能,随着項目和業務的不斷拓展,服務單元數量增多,互相之間的依賴關系更為複雜,可能會出現當某個服務出現問題或網絡原因出現依賴調用出錯或延遲,此時如果調用該依賴的請求不斷增加,Servlet容器的線程資源會被消耗完畢,導緻服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。為了解決這種單點或多點問題造成的連鎖問題,就有了熔斷器的出現。
為了展示熔斷器功能,在之前使用pringcloud搭建的項目的基礎上進行修改
之前搭建的注冊中心:http://blog.csdn.net/chenhaotao/article/details/78677328
服務提供者client:http://blog.csdn.net/chenhaotao/article/details/78677858
服務消費者ribbon:http://blog.csdn.net/chenhaotao/article/details/78678445
服務消費者feign:http://blog.csdn.net/chenhaotao/article/details/78688117
主要實在ribbon或feign項目上實作熔斷功能。
一、在ribbon上實作熔斷器hystrix
改造serice-ribbon 工程的代碼
1.pox.xml檔案中加入hystrix的起步依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
2.在程式啟動類application上添加注解@EnableHystrix開啟hystrix功能
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
public class ServiceRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceRibbonApplication.class, args);
}
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.在service方法上添加注解@HystrixCommand(fallbackMethod = “method”)指定熔斷點并指定熔斷方法
@Service
public class TestService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "testError")
public String testService(String name){
return restTemplate.getForObject("http://SERVICE-HELLO/index?name="+name,String.class);
}
public String testError(String name){
return "sorry, "+name+"通路 SERVICE-HELLO服務 出錯";
}
}
啟動eureka-server注冊中心,再啟動eureka-client服務提供者,最後啟動service-ribbon服務消費者
打開浏覽器通路url:http://localhost:9001/test?name=hao 檢視服務正常時傳回
服務提供者client:hao服務端口:8081
關閉eureka-client,再通路url位址,發現熔斷器已生效,傳回熔斷方法字段
sorry, hao通路 SERVICE-HELLO服務 出錯
這就說明當 SERVICE-HELLO 服務不可用的時候,server-ribbon調用 SERVICE-HELLO的API接口時,會執行快速失敗,直接傳回一組字元串,而不是等待響應逾時,這很好的控制了容器的線程阻塞。
二、在feign上實作熔斷器
feign已經自帶斷容器不需要再單獨引用hystrix依賴,隻不過在feign中熔斷器功能預設是未打開的,需要在配置檔案中開啟。
1.在application.yml中開啟熔斷器
feign:
hystrix:
enabled: true
2.直接在service-feign的TestFeignService接口的@FeignClient注解加上fallback屬性并指定其熔斷類就行了
@FeignClient(value = "SERVICE-HELLO",fallback = TestFeignServiceFallback.class)
public interface TestFeignService {
/**
* @RequestMapping指定調用到服務的那個接口,@RequestParam("name")指定傳入的參數名
*/
@RequestMapping(value = "index",method = RequestMethod.GET)
String testEurekaClient(@RequestParam("name")String name);
}
3.自定義類TestFeignServiceFallback 實作 TestFeignService 接口并在相應的重寫方法中執行熔斷業務
@Component
public class TestFeignServiceFallback implements TestFeignService {
@Override
public String testEurekaClient(String name){
return "sorry, "+name+"通路 SERVICE-HELLO服務 出錯";
}
}
注:自定義的熔斷類還需要加上@Component注解方式注入容器,否則當熔斷執行時會出現找不到類的異常。
啟動eureka-server注冊中心,再啟動eureka-client服務提供者,最後啟動service-ribbon服務消費者
打開浏覽器通路url:http://localhost:9002/testFeign?name=aaa 檢視服務正常時傳回
服務提供者client:aaa服務端口:8081
關閉eureka-client,再通路url位址,發現熔斷器已生效,執行熔斷類傳回熔斷方法字段
sorry, aaa通路 SERVICE-HELLO服務 出錯
附上修改後的項目源碼:
ribbon實作熔斷器:https://pan.baidu.com/s/1bo5UytD
feign實作熔斷器: https://pan.baidu.com/s/1hsu5k7y