前言
在微服務架構中,我們將系統(tǒng)拆分成了一個個的服務單元,各單元應用間通過服務注冊與訂閱的方式互相依賴。由于每個單元都在不同的進程中運行酪穿,依賴通過遠程調用的方式執(zhí)行,這樣就有可能因為網(wǎng)絡原因或是依賴服務自身問題出現(xiàn)調用故障或延遲晴裹,而這些問題會直接導致調用方的對外服務也出現(xiàn)延遲被济,若此時調用方的請求不斷增加,最后就會出現(xiàn)因等待出現(xiàn)故障的依賴方響應而形成任務積壓涧团,線程資源無法釋放只磷,最終導致自身服務的癱瘓,進一步甚至出現(xiàn)故障的蔓延最終導致整個系統(tǒng)的癱瘓泌绣。如果這樣的架構存在如此嚴重的隱患钮追,那么相較傳統(tǒng)架構就更加的不穩(wěn)定。為了解決這樣的問題赞别,因此產(chǎn)生了斷路器等一系列的服務保護機制畏陕。
針對上述問題,在Spring Cloud Hystrix中實現(xiàn)了線程隔離仿滔、斷路器等一系列的服務保護功能惠毁。它也是基于Netflix的開源框架 Hystrix實現(xiàn)的,該框架目標在于通過控制那些訪問遠程系統(tǒng)崎页、服務和第三方庫的節(jié)點鞠绰,從而對延遲和故障提供更強大的容錯能力。Hystrix具備了服務降級飒焦、服務熔斷蜈膨、線程隔離、請求緩存牺荠、請求合并以及服務監(jiān)控等強大功能翁巍。
接下來,我們就從一個簡單示例開始對Spring Cloud Hystrix的學習與使用休雌。
動手試一試
在開始使用Spring Cloud Hystrix實現(xiàn)斷路器之前灶壶,我們先拿之前實現(xiàn)的一些內容作為基礎,其中包括:
-
eureka-server
工程:服務注冊中心杈曲,端口:1001 -
eureka-client
工程:服務提供者驰凛,兩個實例啟動端口分別為2001
下面我們可以復制一下之前實現(xiàn)的一個服務消費者:eureka-consumer-ribbon
,命名為eureka-consumer-ribbon-hystrix
担扑。下面我們開始對其進行改在:
第一步:pom.xml
的dependencies節(jié)點中引入spring-cloud-starter-hystrix
依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
第二步:在應用主類中使用@EnableCircuitBreaker
或@EnableHystrix
注解開啟Hystrix的使用:
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
注意:這里我們還可以使用Spring Cloud應用中的@SpringCloudApplication
注解來修飾應用主類恰响,該注解的具體定義如下所示。我們可以看到該注解中包含了上我們所引用的三個注解涌献,這也意味著一個Spring Cloud標準應用應包含服務發(fā)現(xiàn)以及斷路器胚宦。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}
第三步:改造服務消費方式,新增ConsumerService
類,然后將在Controller
中的邏輯遷移過去间唉。最后绞灼,在為具體執(zhí)行邏輯的函數(shù)上增加@HystrixCommand
注解來指定服務降級方法,比如:
@RestController
public class DcController {
@Autowired
ConsumerService consumerService;
@GetMapping("/consumer")
public String dc() {
return consumerService.consumer();
}
class ConsumerService {
@Autowired
RestTemplate restTemplate;
@HystrixCommand(fallbackMethod = "fallback")
public String consumer() {
return restTemplate.getForObject("http://eureka-client/dc", String.class);
}
public String fallback() {
return "fallback";
}
}
}
下面我們來驗證一下上面Hystrix帶來的一些基礎功能呈野。我們先把涉及的服務都啟動起來低矮,然后訪問localhost:2101/consumer
,此時可以獲取正常的返回被冒,比如:Services: [eureka-consumer-ribbon-hystrix, eureka-client]
军掂。
為了觸發(fā)服務降級邏輯,我們可以將服務提供者eureka-client
的邏輯加一些延遲昨悼,比如:
@GetMapping("/dc")
public String dc() throws InterruptedException {
Thread.sleep(5000L);
String services = "Services: " + discoveryClient.getServices();
System.out.println(services);
return services;
}
重啟eureka-client
之后蝗锥,再嘗試訪問localhost:2101/consumer
,此時我們將獲得的返回結果為:fallback
率触。我們從eureka-client
的控制臺中终议,可以看到服務提供方輸出了原本要返回的結果,但是由于返回前延遲了5秒葱蝗,而服務消費方觸發(fā)了服務請求超時異常穴张,服務消費者就通過HystrixCommand注解中指定的降級邏輯進行執(zhí)行,因此該請求的結果返回了fallback
两曼。這樣的機制皂甘,對自身服務起到了基礎的保護,同時還為異常情況提供了自動的服務降級切換機制悼凑。
更多Spring Cloud內容請持續(xù)關注我的博客更新或在《Spring Cloud微服務實戰(zhàn)》中獲取偿枕。
代碼示例
樣例工程將沿用之前在碼云和GitHub上創(chuàng)建的SpringCloud-Learning項目,重新做了一下整理户辫。通過不同目錄來區(qū)分Brixton和Dalston的示例渐夸。
具體工程說明如下:
- eureka的服務注冊中心:eureka-server
- eureka的服務提供方:eureka-client
- eureka的服務消費者:eureka-consumer-ribbon-hystrix
相關閱讀
- Spring Cloud構建微服務架構:服務注冊與發(fā)現(xiàn)(Eureka、Consul)
- Spring Cloud構建微服務架構:服務消費者(基礎)
- Spring Cloud構建微服務架構:服務消費者(Ribbon)
- Spring Cloud構建微服務架構:服務消費者(Feign)
- Spring Cloud構建微服務架構:分布式配置中心
- Spring Cloud構建微服務架構:服務容錯保護(Hystrix服務降級)
- Spring Cloud構建微服務架構:服務容錯保護(Hystrix依賴隔離)
- Spring Cloud構建微服務架構:服務容錯保護(Hystrix斷路器)
- 更多Spring Cloud內容...