在單體架構中應用Hystrix
Hystrix是一個非常成熟的庫,用於隔離分散式系統中的遠端操作。通常只有在“純”微服務架構中執行時才由開發人員考慮。但是即使我們的專案“只有”一個或兩個連線到外部系統,是否也值得一試呢?
我想是的,但是如果您的專案連線到某些外部系統,可以試試Hystrix。
回退
當連線到外部系統時,我們通常不會考慮如果遠端系統停機我們應該支援什麼回退操作,我們傾向於樂觀並假設,在99%的情況下,這個系統將在沒有任何錯誤的情況下做出響應並且響應速度非常快。一些更成熟的開發人員將處理大多數可預測的錯誤,記錄它們並可能通知使用者操作失敗。如果我們開始使用Hystrix會有什麼變化?
當然,我們會鼓勵(或者甚至強迫)我們考慮在出現錯誤時應該做些什麼,因為Hystrix的基本配置包括為指定的業務操作定義了回退。
讓我們假設我們正在設計一種管理我們書籍的服務。對於我們展示的每本書,我們希望從外部系統載入它的平均價格。在程式碼中它看起來像:
<b>public</b> <b>class</b> BookPriceService { BookPrice fetchPriceFor(BookId bookId) { ... } }
如果我們使用Spring和一個整合庫將Spring與Hystrix(Netflix/Hystrix/tree/master/hystrix-contrib/hystrix-javanica" rel="nofollow,noindex" target="_blank">Hystrix javanica )整合在一起,我們可以輕鬆地更改此程式碼,以便在獲取失敗時支援回退。我們添加了一個註釋和一個回退函式。
<b>public</b> <b>class</b> BookPriceService { @HystrixCommand(fallbackMethod = <font>"undefinedPrice"</font><font>) BookPrice fetchPriceFor(BookId bookId) { </font><font><i>//...</i></font><font> } BookPrice undefinedPrice() { <b>return</b> BookPrice.undefined(); } } </font>
現在,如果我們的服務失敗(確實丟擲了fetchPriceFor方法的一些異常),我們得到具有undefinedPrice的BookPrice(由靜態方法BookPrice.undefined()返回)。現在我們只需要在前端支援這個值並向用戶顯示正確的訊息。
可以為許多其他服務建立這樣的回退(特別是那些獲得一些不重要資訊的服務)。
超時
當遠端呼叫變得滯後時,
處理外部系統變得非常令人沮喪。通常我們沒有為此做好準備,我們將這種滯後傳播到我們的系統甚至終端使用者。讓我們舉例說一下使用者填寫某種表單提交伺服器後,從中獲取資訊,並通過SMTP伺服器傳送電子郵件。在傳送電子郵件之前,使用者填寫的表單將有一個等待顯示正在進行的操作。
如果SMTP伺服器開始響應非常慢,會發生什麼?當花費太長等待時間,使用者會嘗試再次執行它。也許又有了這一個請求,這第二個請求是否會順利進行?
Hystrix將幫助您在系統中配置此類行為,可以設定傳送郵件的方法等待三秒後執行取消操作,執行fallback 。
執行緒池分離
外部系統慢還導致一個問題 - 執行緒池會用光,當越來越多的執行緒執行遠端呼叫並且它們永遠留在那裡無法收回到執行緒池時會發生什麼?當然我們所有的執行緒都掛在這個呼叫上,我們正在消耗越來越多的執行緒。在最糟糕的情況下,我們最終可能沒有更多的執行緒來處理與伺服器的任何額外連線,因為它們都在等待外部系統。
令人恐懼的是,某些只涉及我們所有系統功能的某些部分的外部系統可能會破壞我們的整個專案。
Hystrix再次幫助我們以幾乎零成本避免這種情況。預設情況下,如前面的示例所示配置Hystrix時,Hystrix將建立另外一個執行緒池,該池與應用程式伺服器中的預設池分開。當然你可以調整這個執行緒池來改變它的大小,queueSize和許多其他(這裡 都描述)。
現在,如果Hystrix中的所有執行緒都將被消耗,您可以拒絕接下來的執行緒或進行幾個排隊。一般情況下,您可以按照您希望的方式調整它,不要拒絕太多的請求,也不要在執行時停留太長時間。
而且你不僅可以配置一個執行緒池。例如,如果為每個系統連線到2個外部系統,則可以配置不同的執行緒池。或者甚至在使用一個系統進行一些非常持久的遠端呼叫時,您可以使用不同的執行緒池設定。
配置多個執行緒池不是零成本。您需要考慮到它會增加上下文切換和計算機負載。
斷路器
我想提到的Hystrix的最後一件事是斷路器模式。簡而言之,Hystrix正在測量每次呼叫遠端系統的統計資料。如果故障超過某些閾值,則Hystrix會自動拒絕下一次呼叫而不呼叫外部系統(Hystrix將此外部系統標記為“關閉”)。當然並非所有請求都被拒絕 - Hystrix將不時繞過一個請求以檢查系統是否已啟動。
如果否,則再次下一次請求被自動拒絕而不呼叫外部系統直到下次測試請求到來。
如果測試請求成功,那麼我們將清除所有先前的統計資訊並轉到初始狀態
這個解決方案有哪些優勢?首先,我們不會向外部系統新增更多呼叫,因為它看起來在快速響應時存在實際問題。多虧了這一點,它可以嘗試從緩慢恢復到正常狀態。其次,我們不必等待超時才能發現外部系統已關閉:如果Hystrix處於“拒絕”狀態,我們會在零時間內拒絕遠端呼叫(快速失敗)。