在微服務架構中, 根據業務來拆分成一個個的服務,服務與服務之間可以相互調用(RPC),在Spring Cloud可以用RestTemplate+Ribbon和Feign來調用。爲了保證其高可用,單個服務通常會集羣部署。由於網絡原因或者自身的原因,服務並不能保證100%可用,如果單個服務出現問題,調用這個服務就會出現線程阻塞,此時若有大量的請求涌入,程資源會被消耗Servlet容器的線完畢,導致服務癱瘓。服務與服務之間的依賴性,故障會傳播,會對整個微服務系統造成災難性的嚴重後果,這就是服務故障的“雪崩”效應。
爲了解決這個問題,業界提出了斷路器模型。
一、斷路器簡介
Netflix 開源了Hystrix組件,實現了斷路器模式,Spring Cloud 對這一組件進行了整合。在微服務中,一個請求調用多個服務是很常見的事情。如下圖:
較底層的服務如果出現故障,會導致連鎖故障。當對特定的服務的調用的不可用達到一個閥值(Hystric 是5秒20次) 斷路器將會被打開。
斷路打開後,可用避免連鎖故障,fallback方法可以直接返回一個固定值。
二、 準備工作
接着上篇文章的工程,啓動端口號爲8761 的 eureka-server 工程,啓動 端口號爲8762 的 eureka-client 工程。
三、在ribbon 使用斷路器
改造 eureka-ribbon 工程的代碼,首先在pom文件裏 加入依賴 spring-cloud-starter-netflix-hystrix
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
在啓動類上 加入註解 @EnableHystrix 開啓 Hystrix:
@EnableHystrix // 引入斷路器模型
@EnableEurekaClient
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonApplication.class, args);
System.out.println("================eureka-ribbon 啓動成功=================");
}
@Bean
@LoadBalanced // 開啓負載均衡 功能
RestTemplate restTemplate(){
return new RestTemplate();
}
}
改造 HelloService 類,在hiService方法上加上 @HystrixCommand 註解。該註解對該方法創建了熔斷器的功能,並指定了fallbackMethod熔斷方法,熔斷方法直接返回一個字符串,字符串爲 "hi, "+ name + “, sorry error!”;
@Service
public class HelloService {
@Autowired
private RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "hiError")
public String hiService(String name){
return restTemplate.getForObject("http://EUREKA-CLIENT/hi?name="+name, String.class);
}
public String hiError(String name){
return "hi, "+ name + ", sorry error!";
}
}
啓動 eureka-ribbon 工程,訪問 http://localhost:8764/hi?name=lbh,瀏覽器 顯示: hi lbh ,i am from port:8762
當關閉eureka-client 工程時,再次訪問,瀏覽器 顯示: hi, lbh, sorry error!
此時,斷路器起作用了。當eureka-client 工程不可用時,eureka-ribbon 調用 eureka-client 的API接口時,會執行快速失敗,返回一組字符串,而不是等待響應超時,這很好控制了 容器的線程阻塞。
四、Feign 中使用斷路器
feign 是自帶斷路器功能的,在 D版本的spring cloud 之後,它沒有默認開啓,需要在配置文件中開啓:
feign:
hystrix:
enabled: true # 開啓 feign 斷路器模式
基於 eureka-feign 工程進行改造,只需要在 FeignClient 的 SchedualServiceHi接口的註解中加上fallback的指定類就行了:
/**
*
* 注: 啓用斷路器 只需要在 @FeignClient()註解中加上 fallback 屬性就可以了,SchedualServiceHiHystric 實現改接口。
* Created by Advancer on 2019/1/17 10:46.
* auth: lbh
*/
@Component
@FeignClient(value = "eureka-client", fallback = SchedualServiceHiHystric.class)
public interface SchedualServiceHi {
@RequestMapping(value = "/hi", method = RequestMethod.GET)
String sayHiFromClientOne(@RequestParam(value = "name") String name);
}
SchedualServiceHiHystric需要實現SchedualServiceHi 接口,並注入到Ioc容器中,代碼如下:
@Component
public class SchedualServiceHiHystric implements SchedualServiceHi {
@Override
public String sayHiFromClientOne(String name) {
return "sorry "+ name;
}
}
啓動 eureka-feign 工程,瀏覽器 打開 http://localhost:8765/hi?name=lbh ,瀏覽器 顯示: hi lbh ,i am from port:8762
沒有啓動的情況下 顯示: sorry lbh
此時,斷路器起到作用了。
源碼下載地址:
https://github.com/JavaAdvancer/eurekademo
參考文章:
https://www.fangzhipeng.com/springcloud/2017/07/12/sc04-hystrix/