天天看點

springcloud微服務四:服務容錯保護Hystrix斷路器

通過前邊的學習,服務注冊中心、服務提供者和服務消費者都成功建立并運作起來,而且通過預設的配置resttemplate及@loadbalanced注解開啟了負載均衡。

在預設的情況下,負載均衡政策是線性輪詢的方式,也就是說在用戶端擷取到的服務清單中依次交替,例如開啟了三個服務server1、server2、server3,那麼線上性輪詢時,就會按這個順序來調用。

我之前是開啟了兩個服務,一個端口是1001,另一個是2001,那麼在之前的這種情況下,如果我關閉其中一個服務,就比如這裡關閉1001端口的服務,當再次通路的時候,每通路兩次,就會有一次是如下的error page:

同時背景也會列印出錯誤日志:

其實這個問題的原因就是,用戶端的服務清單并不是在服務關閉的瞬間就會同步更新,而是根據它自己配置的更新服務清單間隔的時間每隔一段時間去注冊中心擷取一次。

是以,雖然這裡我關閉了1001端口,但是實際上用戶端并不知道,在它負載均衡進行線性輪詢時,依舊會輪詢之前儲存的服務清單,但是發送請求後卻發現這個服務執行個體并不存在,無法連接配接,于是就出現了上邊的500錯誤。

這裡為了示範,我是主動關閉了服務,但實際生産的過程中,難免會出現服務當機或者網絡故障等方面的問題,進而導緻類似的無法連接配接到服務執行個體的情況。

那麼這時候正常來說在這個故障恢複之前是不應該繼續連接配接的,起碼就算連接配接了也應該給使用者展示更加友好的界面或其他資訊,至于具體的情況就需要具體對待了。

而解決這個問題,就引出了服務容錯保護機制hystrix,也叫斷路器。

既然之前說了消費方儲存的服務清單是自己主動擷取的,并非被動推送來的,那麼可想而知這個斷路器的定義也應該是在服務消費方。

首先需要引入hystrix相應的依賴,在之前的消費端pom.xml的基礎上加上如下的配置:

同時在服務消費端的主類加上@@enablecircuitbreaker注解,這個注解的作用就是開啟斷路器功能,所謂的主類就是具有main方法的那個類,修改之後這裡的代碼如下:

這裡實際上有一點需要說明的是,這個類上邊的三個注解其實是可以用一個注解代替的,這個注解是@springcloudapplication,通過源碼可以知道這個注解包含了上述三個注解,也意味着一個标準的springcloud應用是應該包括服務的注冊發現以及斷路器功能的。

那麼除開主類加一個注解之外,原本的服務類也需要有一定的修改,首先是在原本調用的方法上加上@hystrixcommand(fallbackmethod = “helloerror”),意思是當調用的服務出現故障的時候回調helloerror方法,或者說當調用服務出現故障的時候復原一步,然後轉而調用helloerror方法。

不管怎樣,既然要調用helloerror方法,很顯然需要存在這個方法,是以還需要加入一個helloerror方法,當然了這個方法名是自定義的,裡邊的邏輯也是要根據具體的業務需要定義的,我這裡就很簡單的傳回一個字元串,修改之後的代碼如下:

就這樣,一個簡單地斷路器功能就實作了,為了證明确實有效,我在兩個服務正常運作的情況下再次關閉其中一個,然後再在浏覽器通路的時候就不會再出現之前的500提示,背景也同樣不再有error的日志,證明成功的處理了的這種故障,浏覽器通路結果如圖:

springcloud微服務四:服務容錯保護Hystrix斷路器

當然了,我這裡示範的時候,為了友善都是直接關掉了其中一台伺服器,這相當于實際生産中的伺服器突然當機或者程序突然中斷的情況,而實際上這種情況發生的幾率還是比較少的。

由于在分布式高可用的系統中,一般不同的服務是部署在不同的伺服器上,不同的伺服器間就會涉及到網絡通訊和資料傳輸,是以正常來說網絡故障導緻服務異常的情況會更多一些。

如果要示範這種情況,就可以在服務接收請求到傳回資料之前加入線程休眠,進而模拟網絡阻塞,隻需要注意hystrix的預設逾時時間是2000毫秒,也就是2秒就夠了。

繼續閱讀