hystrix应用 博客_用Hystrix保护您的应用程序
hystrix應用 博客
在先前的帖子http://www.javacodegeeks.com/2014/07/rxjava-java8-java-ee-7-arquillian-bliss.html中,我們討論了微服務以及如何使用(RxJava)的Reactive Extensions編排微服務。 但是,如果一項或多項服務因已停止或引發異常而失敗,該怎么辦? 在像微服務體系結構這樣的分布式系統中,正常的情況是遠程服務可能會失敗,因此它們之間的通信應該是容錯的,并且可以適當地管理網絡呼叫中的延遲。
而這正是Hystrix所做的。 Hystrix是一個延遲和容錯庫,旨在隔離對遠程系統,服務和第三方庫的訪問點,停止級聯故障,并在不可避免發生故障的復雜分布式系統中實現彈性。
在像微服務這樣的分布式體系結構中,一個服務可能需要使用其他服務作為依賴項來完成其工作。 應用程序中通過網絡或客戶端庫伸出的每一個可能導致網絡請求的點都是失敗的根源。 比故障更糟的是,這些應用程序還可能導致服務之間的延遲增加。 這給我們帶來了另一個大問題,假設您正在Tomcat上開發一個服務,該服務將打開兩個服務的兩個連接,如果該服務中的一個花費比預期多的時間來發送響應,那么您將花費一個線程。 Tomcat池(當前請求之一)不執行任何操作,而是等待一個答案。 如果您的網站流量不高,這可能是可以接受的,但是如果您的流量很大,則所有資源可能會變得飽和并阻塞整個服務器。
Hystrix Wiki提供了這種情況下的模式:
避免先前問題的方法是添加一個線程層,以將每個依賴項彼此隔離。 因此,每個依賴項(服務)可能包含一個線程池以執行該服務。 在Hystrix中,此層由HystricxCommand對象實現,因此對外部服務的每次調用都被包裝為在不同的線程中執行。
Hystrix Wiki提供了此方案的模式:
而且Hystrix還提供其他功能:
- 每個線程都有一個超時,因此調用可能不會無限等待響應。
- 在可行的情況下執行故障預置,以保護用戶免受故障的影響。
- 衡量成功,失敗(客戶端拋出的異常),超時和線程拒絕,并進行監視。
- 實現斷路器模式,如果錯誤百分比超過閾值,該模式將在一段時間內自動或手動停止所有對外部服務的請求。
因此,讓我們從一個非常簡單的示例開始:
public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String run() throws Exception {return "Hello World";} }然后,我們可以使用execute方法以同步方式執行該命令。
new HelloWorldCommand().execute();盡管此命令是同步的,但它是在不同的線程中執行的。 默認情況下, Hystrix為在同一HystrixCommandGroupKey中定義的每個命令創建一個線程池。 在我們的示例中, Hystrix創建了一個線程池,該線程池鏈接到分組到HelloWorld線程池的所有命令。 然后對于每次執行,都會從池中獲取一個線程來執行命令。
但是我們當然可以異步執行命令(這完全適合異步JAX-RS 2.0或Servlet 3.0規范 )。 為此,只需運行:
Future<String> helloWorldResult = new HelloWorldCommand().queue(); //some more work Stirng message = helloWorldResult.get();實際上,同步調用是由Hystrix在內部實現的,它返回新的HelloWorldCommand()。queue()。get();。 內部。
我們已經看到我們可以同步和異步執行命令,但是還有第三種方法是使用RxJava進行React式執行(您可以在我之前的文章http://www.javacodegeeks.com/2014/07/中了解有關RxJava的更多信息rxjava-java8-java-ee-7-arquillian-bliss.html )。
為此,您只需要調用observe方法:
Observable<String> obs = new HelloWorldCommand().observe(); obs.subscribe((v) -> {System.out.println("onNext: " + v); }但是有時情況會出錯,命令的執行可能會引發異常。 從run()方法拋出的所有異常( HystrixBadRequestException除外) 均計為失敗并觸發getFallback()和斷路器邏輯(更多有關斷路器)。 您不希望將其視為服務故障的任何業務異常(例如非法參數)都必須包裝在HystrixBadRequestException中 。
但是服務故障會如何處理, Hystrix可以為我們做什么? 總之, Hystrix可以提供兩件事:
倒退
發生異常( HystrixBadRequestException除外)時調用的方法是getFallback() 。 您可以重寫此方法并提供自己的實現。
public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String getFallback() {return "Good Bye";}@Overrideprotected String run() throws Exception {//return "Hello World";throw new IllegalArgumentException();} }斷路器
斷路器 r是一種檢測故障并避免不斷接收相同錯誤的軟件模式。 而且,如果服務是遠程的,則可以在不等待TCP連接超時的情況下引發錯誤。
假設下一個典型示例:一個系統每秒需要訪問數據庫100次,但它失敗了。 每秒將引發100次相同的錯誤,并且由于與遠程數據庫的連接意味著存在TCP連接,因此每個客戶端將等待直到TCP超時到期。
因此,如果系統可以檢測到服務出現故障并避免客戶端在一段時間內發出更多請求,這將非常有用。 這就是斷路器的作用。 對于每次執行,請檢查電路是否斷開(跳閘),這意味著發生了錯誤,并且該請求將不發送給服務,并且將執行后備邏輯。 但是,如果電路是閉合的,則該請求將被處理并且可以正常工作。
Hystrix維護一個統計數據庫,其中包含成功請求與失敗請求的數量。 當Hystrix在規定的空閑時間內檢測到失敗命令的閾值時,它將斷開電路,因此以后的請求將能夠盡快返回錯誤,而不必將資源消耗到可能處于脫機狀態的服務中。 但好消息是, Hystrix還是負責關閉電路的負責人。 經過一段時間后, Hystrix將嘗試再次運行傳入的請求,如果此請求成功,則它將關閉電路,否則將保持電路斷開。
在Hystrix網站的下一張圖中,您可以看到Hystrix與電路之間的相互作用。
既然我們已經了解了Hystrix的基礎知識,那么讓我們看看如何編寫測試以檢查Hystrix是否按預期工作。
測試前的最后一件事。 在Hystrix中,有一個名為HystrixRequestContext的特殊類。 此類包含狀態并管理請求的生命周期。 例如,如果要Hystrix管理緩存結果或出于日志記錄目的,則需要初始化此類。 通常,此類在啟動業務邏輯之前(例如,在Servlet Filter中 )初始化,并在處理請求后結束。
讓我們使用先前的HelloWorldComand來驗證電路斷開時是否調用了fallback方法。
public class HelloWorldCommand extends HystrixCommand<String> {public HelloWorldCommand() {super(HystrixCommandGroupKey.Factory.asKey("HelloWorld"));}@Overrideprotected String getFallback() {return "Good Bye";}@Overrideprotected String run() throws Exception {return "Hello World";} }和測試。 請記住,出于學術目的,我在測試中添加了很多斷言。
@Test public void should_execute_fallback_method_when_circuit_is_open() {//Initialize HystrixRequestContext to be able to get some metricsHystrixRequestContext context = HystrixRequestContext.initializeContext();HystrixCommandMetrics creditCardMetrics = HystrixCommandMetrics.getInstance(HystrixCommandKey.Factory.asKey(HelloWorldRestCommand.class.getSimpleName()));//We use Archaius to set the circuit as closed.ConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.forceOpen", false);String successMessage = new HelloWorldRestCommand().execute();assertThat(successMessage, is("Hello World"));//We use Archaius to open the circuitConfigurationManager.getConfigInstance().setProperty("hystrix.command.default.circuitBreaker.forceOpen", true);String failMessage = new HelloWorldRestCommand().execute();assertThat(failMessage, is("Good Bye"));//Prints Request => HelloWorldRestCommand[SUCCESS][19ms], HelloWorldRestCommand[SHORT_CIRCUITED, FALLBACK_SUCCESS][0ms] System.out.println("Request => " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString());assertThat(creditCardMetrics.getHealthCounts().getTotalRequests(), is(2));assertThat(creditCardMetrics.getHealthCounts().getErrorCount(), is(1));}這是一個非常簡單的示例,因為execute方法和fallback方法非常簡單,但是如果您認為execute方法可能包含復雜的邏輯,而fallback方法也可能是如此復雜(例如,從另一臺服務器檢索數據,則生成某種存根數據,…),然后編寫集成或功能測試以驗證所有這些有意義的流程。 請記住,有時您的后備邏輯可能取決于當前用戶或其他用戶的先前調用。
Hystrix還提供其他功能,例如兌現結果,因此在同一HystrixRequestContext中已經執行的任何命令都可以返回緩存結果( https://github.com/Netflix/Hystrix/wiki/How-To-Use#Caching )。 它提供的另一個功能是折疊。 它支持將請求自動批處理為單個HystrixCommand實例執行。 它可以使用批處理大小和時間作為執行批處理的觸發器。
如您所見, Hystrix是一個非常簡單但功能強大的庫,如果您的應用程序調用外部服務,則應考慮這一點。
我們不斷學習,
亞歷克斯
唱一首歌,你是鋼琴家,今晚唱一首歌,好吧,我們都在想起旋律,而且你讓我們感覺很好(鋼琴家–比利·喬爾)
音樂: https : //www.youtube.com/watch?v = gxEPV4kolz0
翻譯自: https://www.javacodegeeks.com/2014/09/defend-your-application-with-hystrix.html
hystrix應用 博客
總結
以上是生活随笔為你收集整理的hystrix应用 博客_用Hystrix保护您的应用程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何彻底屏蔽金蝶后门(win10如何关闭
- 下一篇: win7蓝牙设置(win7蓝牙设置没反应