服務降級之Hystrix使用
一、什麼是服務降級、服務熔斷和限流?
複雜的分散式體系結構中服務之間的依賴較多,進行服務呼叫時不可避免出現呼叫失敗的情況,而且呼叫往往呈現鏈式呼叫,某一環節出現錯誤將會導致致命問題,產生可怕的“服務雪崩”效應,導致整個系統故障。為了解決上述這個問題,我們需要一定的手段來保證核心服務能夠正常執行,因此需要臨時丟棄或隔離這些出現問題的服務,這就是服務降級和熔斷。要注意的是服務降針對的是非核心服務,有些服務是不能進行降級和熔斷的,核心服務的熔斷和降級意味著整體業務體系無法使用,比如購物車結算服務等。
服務降級和服務熔斷及限流是有區別的:
1、降級體現在即使呼叫的服務出現問題時,任然向上級返回一個友好的提示(比如返回伺服器忙,請稍後再試),不向上級丟擲錯誤,不讓上級等待。程式執行異常、超時、服務熔斷觸發服務降級、執行緒池滿等情況都會導致服務降級。
2、熔斷類似於保險絲,體現在當達到最大訪問負載後,直接跳閘拒絕服務,然後觸發降級方法返回友好的提示。
3、限流體現在控制訪問併發量,嚴禁某一時間段內出現大量的訪問。
在考慮降級之前,需要進行整體的業務系統分析,確保哪些服務是可以降級的。超時不再等待,宕機要有兜底解決方案......整理一套降級方案。常見的服務降級方案:訪問超時降級、頻率超限降級、服務故障降級、人工預警降級等。
二、什麼是Hystrix?
Hystrix是一個用於處理分散式系統延遲和容錯的開源庫,它能保證在某一個服務出現問題的情況下,不會導致整體服務的聯級故障,以提高分散式系統的彈性。Hystrix支援服務降級、服務熔斷、實時監控、服務限流、隔離等功能,一般用於服務消費者模組中做降級(也可以用於服務提供者模組),但目前官網已停止更新,進入維護階段。
三、Hystrix的使用
1、修改Pom檔案,引入jar包
<! --hystrix--> <dependency> <groupId>org.springframework.cloud</ groupId> <artifactId>spring-cloud-starter-nftflix-hystrix</artifactId> </dependency>
2、業務方法上增加@HystrixCommand(fallbackMethod = "falltHandler")註解,表示如果使用該註解的方法報錯了,就呼叫fallbackMethod 指定的兜底方法執行處理流程。
@HystrixCommand(fallbackMethod="falltHandler")
public string methodserver()
{
int age = 10/0; return "嘗試呼叫微服務模組。。";
}
public string falltHandler()
{ return "伺服器錯誤,請稍後再試!";
}
3、業務方法上增加@HystrixCommand(fallbackMethod = "falltHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds" , value="3000")})註解,表示如果使用該註解的方法執行超過3秒中,就呼叫fallbackMethod 指定的兜底方法執行處理流程。
@HystrixCommand(fallbackMethod = "falltHandler",commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds" , value="3000")}) public string methodserver() { //等待3秒中... return "嘗試呼叫微服務模組。。"; } public string falltHandler() { return "對方伺服器超時,請稍後再試!"; }
4、如果需要feign等元件支援Hystrix,還需要完成一下兩步
a.主啟動類上增加@EnableCircuitBreaker註解
b.在application.yml配置檔案中增加以下程式碼
feign: hystrix: enabled: true
四、全域性兜底方法配置
以上程式碼的實現中,每個方法都對應一個兜底方法,這導致了程式碼膨脹,有時候很多方法可以公用一個預設兜底方法來進行處理,hystrix提供了一個註解@Defaultproperties(defaultFallback = “Global_FallbackMethod")來指定這個預設的兜底方法,該註解作用與類上。如果該類的方法上有指定的兜底方法則使用指定的兜底方法,否則使用這個預設的兜底方法。
@Restcontroller
@DefaultProperties(defaultFallback = "global_FallbackMethod")
public class Hvstirxcontroller { public string global_FallbackMethod()
{
return "全域性兜底方法!";
}
}
五、微服務介面降級處理
按照前面說的,都在業務方法上增加兜底方法,進行降級處理,也一定會導致程式碼臃腫,與其在Controller層對所有方法設定降級,還不如在呼叫微服務的介面類中去統一處理。Feign結合hystrix(要注意開啟結合功能,詳見前面介紹的開啟方法)提供了一種實現方式,實現步驟:
1、新增一個類FallbackService實現微服務介面類,重寫微服務介面中方法。
2、在微服務介面類上增加註解@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX",fallback = FallbackService.class)。
完成以上兩步設定後,微服務介面方法將以FallbackService類中重寫的方法作為它的兜底方法,當微服務介面方法調用出錯時,就會執行對應的重寫方法。
六、斷路器
斷路器是Hystrix實現服務熔斷的一種機制,熔斷機制是應對服務雪崩的一種保護,當呼叫鏈路出現問題時,會先進行服務降級,進而熔斷該節點的呼叫,當檢測到節點恢復正常後,再次恢復鏈路呼叫。在SpringCloud框架中熔斷機制是通過Hystrix實現的,Hystrix會監控微服務的呼叫狀況。斷路器本身有三種狀態,開啟、關閉和半開狀態。當斷路器在開啟狀態不允許呼叫、在關閉狀態允許呼叫、半開狀態嘗試呼叫,若呼叫成功後狀態變成關閉狀態,反正變成開啟狀態。
Hystrix中@HystrixCommand註解提供瞭如下幾個引數,用於配置斷路器
@HystrixCommand(
fallbackMethod = "CircuitBreaker_fallback",
commandProperties =
{ @HystrixProperty(name = "circuitBreaker.enabled" , value = "true" ), @HlystrixProperty(name = "circuitBreaker.requestVolumeThreshold" ,value = "10"), @HystrixProperty(name = "circuitBreaker.sleepwindowInMi1liseconds" , value = "1000"),
@HlystrixProperty(name = "circuitBreaker.errorThresholdPercentage" , value = "60") })
其中,fallbackMethod指定兜底方法,即當服務呼叫異常或斷路器狀態在開啟(與circuitBreaker.enabled指定的狀態概念不同)狀態時呼叫的處理方法。circuitBreaker.enabled指定是否啟用斷路器功能,circuitBreaker.requestVolumeThreshold指定請求次數峰值(達到峰值後跳閘),circuitBreaker.sleepwindowInMiliseconds指定時間間隔(統計峰值和失敗率的時間段),circuitBreaker.errorThresholdPercentage指定失敗率(失敗率達到後跳閘)。例子如下
//=====服務熔斷 @HystrixCommand(fallbacknethod = "circuitBreaker_fallback" ,commandProperties = { @HystrixProperty(name = "circuitBreaker.enabled" , value =“true"), @HystrixProperty(name = "circuitBreaker.requestvolumeThreshold",value = "100"), @HystrixProperty(name = "circuitBreaker.sleepwindowInNi1liseconds" ,value = "1000"), @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage" ,value = "60") }) public string CircuitBreaker(@Pathvariable("id") Integer id)
{ if(id < 0) { throw new RuntimeException(”*id不能負數");
} return Thread.currentThread( ).getName( )+""\t"+"呼叫成功!";
}
public string circuitBreaker_fallback(@Pathvariable("id") Integer id) { return "id 不能負數,請稍後再試!";
}
上述表示,在1秒鐘內如果呼叫失敗率達到60%或者請求達到峰值100次,則直接跳閘執行circuitBreaker_fallback方法。斷路器在開啟狀態時,隔一段時間(預設5秒)會將狀態轉換為半開狀態,後續請求會嘗試呼叫鏈路,若成功則將斷路器置為關閉狀態,正常執行CircuitBreaker方法,否則繼續將斷路器狀態變為開啟狀態,執行circuitBreaker_fallback方法。
除了上述的基本配置功能外,Hystrix還提供了其他的配置項,請參考某大神的https://www.cnblogs.com/throwable/p/11961016.html,這裡不在詳述。
七、Hystrix服務監控儀表盤Dashboard
Hystrix提供了實時的服務監控介面,Hystrix會持續第記錄所有通過Hystrix發起的請求,並以報表和圖形的形式展示給使用者,SpringCloud整合了HystrixDashboard,把監控的內容轉化成視覺化介面。
建立Hystrix服務監控程式的步驟:1建立模組,2POM引入jar包,3配置yml配置檔案,4主啟動類上增加@EnableHystrixDashboard註解,5被監控的服務配置依賴,6啟動服務訪問服務地址顯示web視覺化介面。
1、監控服務模組需要引入dashboard的jar包
<dependency> <groupId>org.springframework.cloud</groupid> <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId> </dependency>
2、被監控的服務模組需要引入actuator的jar包,而且要在主啟動類上增加@EnablecircuitBreaker註解。
<! -- actuator監控資訊模組--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
注意:新版本springcloud的被監控服務模組需要在主啟動類下增加如下程式碼,否則可能導致無法顯示監控資料
/** *此配置是為了服務監控而配置,與服務容錯本身無關,springcloud升級後的坑 *ServLetRegistrationBean因為springboot的預設路徑不是"/hbystcix.stream",*只要在自已的專案裡配置上下面的servlet就可以了 */ @Bean public servletRegistrationBean getservlet() { HystrixMetricsstreamServlet streamServlet = new HystrixMetricsstreamServlet(); ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamservlet);
registrationBean.setLoadonstartup(1); registrationBean.addurlMappings("/hystrix.stream" ); registrationBean.setName("HystrixMetricsstreamservlet");
return registrationBean;
}
3、web視覺化頁面啟動成功後,在位址列輸入要監控的微服務的地址,即可對該服務實現監控,介面如下
八、Hystrix工作流程圖