以前我寫過一篇博文,經過案例瞭解Hystrix的各類基本使用方式,在這篇文章裏,咱們是經過Hystrix調用正常工做的服務,也就是說,Hytrix的保護機制並無起做用,這裏咱們將在HystrixProtectDemo.java裏演示調用不可用的服務時,hystrix啓動保護機制的流程。這個類是基於NormalHystrixDemo.java改寫的,只是在其中增長了getFallback方法,代碼以下。 html
1 //省略必要的package和import代碼 2 public class HystrixProtectDemo extends HystrixCommand<String> { 3 RestClient client = null; 4 HttpRequest request = null; 5 //構造函數很類似 6 public HystrixDemoProtectDemo() { 7 super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); 8 } 9 //initRestClient方法沒變 10 private void initRestClient(){ 11 //和NormalHystrixDemo.java同樣,具體請參考代碼 12 } 13 //run方法也沒變 14 protected String run() { 15 //和NormalHystrixDemo.java同樣,具體請參考代碼 16 } 17 //此次多個了getFallback方法,一旦出錯,會調用其中的代碼 18 protected String getFallback() { 19 //省略跳轉到錯誤提示頁面的動做 20 return "Call Unavailable Service."; 21 } 22 //main函數 23 public static void main(String[] args) { 24 HystrixDemoProtectDemo normalDemo = new HystrixDemoProtectDemo(); 25 normalDemo.initRestClient(); 26 try { 27 Thread.sleep(1000); 28 } catch (InterruptedException e) { 29 e.printStackTrace(); 30 } 31 String result = normalDemo.execute(); 32 System.out.println("Call available function, result is:" + result); 33 } 34 }
這個類裏的構造函數和NormalHystrixDemo.java很類似,而initRestClient和run方法根本沒變,因此就再也不詳細給出了。前端
在第18行裏,咱們重寫了HystrixCommand類的getFallback方法,在其中定義了一旦訪問出錯的動做,這裏僅僅是輸出一段話,在實際的項目裏,能夠跳轉到相應的錯誤提示頁面。java
而main函數裏的代碼和NormalHystrixDemo.java裏的徹底同樣,只是,在運行這段代碼前無需運行HystrixServerDemo項目的啓動類,這樣服務必定是調用不到的。運行本段代碼後,咱們能看到以下的結果。 數據庫
In run瀏覽器
Call available function, result is:Call Unavailable Service.緩存
從第2行的輸出上,咱們能確認,一旦調用服務出錯,Hystrix處理類能自動地調用getFallback方法。服務器
若是這裏沒有定義getFallback方法,那麼一旦服務不可用,那麼用戶可能在鏈接超時以後,在瀏覽器裏看到一串毫無心義的內容,這樣用戶體驗就不好,若是整個系統的其它容錯措施也沒到位,甚至就有可能致使當前和下游模塊癱瘓。併發
相反,在這裏因爲咱們在hystirx提供的getFallback方法裏作了充分的準備,那麼一旦出現錯誤,這段錯誤處理的代碼能被當即觸發,其效果就至關於熔斷後繼的處理流程。函數
由getFallback出面,友好地告知用戶出問題了,以及後繼該如何處理,這樣一方面能及時熔斷請求從而保護整個系統,另外一方面不會形成因體驗過差而用戶大規模流失的狀況。post
若是每次請求都要走後臺應用程序乃至再到數據庫檢索一下數據,這對服務器的壓力太大,有時候這一因素甚至會成爲影響網站服務性能的瓶頸。因此,大多數網站會把一些無需實時更新的數據放入緩存,前端請求是到緩存裏拿數據。
Hystrix在提供保護性便利的同時,也能支持緩存的功能,在下面的HystrixCacheDemo.java裏,咱們將演示Hystrix從緩存中讀取數據的步驟,代碼以下。
1 //省略必要的package和import代碼 2 public class HystrixCacheDemo extends HystrixCommand<String> { 3 //用戶id 4 Integer id; 5 //用一個HashMap來模擬數據庫裏的數據 6 private HashMap<Integer,String> userList = new HashMap<Integer,String>(); 7 //構造函數 8 public HystrixCacheDemo(Integer id) { 9 super(HystrixCommandGroupKey.Factory.asKey("RequestCacheCommand")); 10 this.id = id; 11 userList.put(1, "Tom"); 12 }
在第3行裏,咱們定義了一個用戶id,並在第6行定義了一個存放用戶信息的HashMap。
在第8行的構造函數裏,咱們在第10行裏用參數id來初始化了本對象的id屬性,並在第11行裏,經過put方法模擬地構建了一個用戶,在項目裏,用戶的信息實際上是存在數據庫裏的。
13 protected String run() { 14 System.out.println("In run"); 15 return userList.get(id); 16 }
若是不走緩存的話,第13行定義run函數將會被execute方法觸發,在其中的第15行裏,咱們經過get方法從userList這個HashMap裏得到一條用戶數據,這裏咱們用get方法來模擬根據id從數據庫裏獲取數據的諸多動做。
17 protected String getCacheKey() { 18 return String.valueOf(id); 19 }
第17行定義的getCacheKey方法是Hystrix實現緩存的關鍵,在其中咱們能夠定義「緩存對象的標準」,具體而言,咱們在這裏是返回String.valueOf(id),也就是說,若是第二個HystrixCacheDemo對象和第一個對象具備相同的String.valueOf(id)的值,那麼第二個對象在調用execute方法時,就能夠走緩存。
public static void main(String[] args) { 21 //初始化上下文,不然沒法用緩存機制 22 HystrixRequestContext context = HystrixRequestContext.initializeContext(); 23 //定義兩個具備相同id的對象 24 HystrixCacheDemo cacheDemo1 = new HystrixCacheDemo(1); 25 HystrixCacheDemo cacheDemo2 = new HystrixCacheDemo(1); 26 //第一個對象調用的是run方法,沒有走緩存 27 System.out.println("the result for cacheDemo1 is:" + cacheDemo1.execute()); 28 System.out.println("whether get from cache:" + cacheDemo1.isResponseFromCache); 29 //第二個對象,因爲和第一個對象具備相同的id,因此走緩存 30 System.out.println("the result for cacheDemo2 is:" + cacheDemo2.execute()); 31 System.out.println("whether get from cache:" + cacheDemo2.isResponseFromCache); 32 //銷魂上下文,以清空緩存 33 context.shutdown(); 34 //再次初始化上下文,但因爲緩存已清,因此cacheDemo3沒走緩存 35 context = HystrixRequestContext.initializeContext(); 36 HystrixCacheDemo cacheDemo3 = new HystrixCacheDemo(1); 37 System.out.println("the result for 3 is:" + cacheDemo3.execute()); 38 System.out.println("whether get from cache:" + cacheDemo3.isResponseFromCache); 39 context.shutdown();
在第20行的main方法裏,咱們定義了以下的主要邏輯。
第一,在第22行,經過initializeContext方法,初始化了上下文,這樣才能啓動緩存機制。,在第24和25行裏,咱們建立了兩個不一樣名的,但相同id的HystrixCacheDemo對象。
第二,在第27行裏,咱們經過cacheDemo1對象的execute方法,根據id查找用戶,雖然咱們在這裏是經過run方法裏第15行的get方法從HashMap裏取數據,但你們能夠把這想象成從數據表裏取數據。
第三,在第30行裏,咱們調用了cacheDemo2對象的execute方法,因爲它和cacheDemo1對象具備相同的id,因此這裏並無走execute方法,而是直接從保存cacheDemo1.execute的緩存裏拿數據,這就能夠避免因屢次訪問數據庫而形成了系統損耗。
第四,咱們在第33行銷燬了上下文,並在第35行裏從新初始化了上下文,以後,雖然在第36行定義的cacheDemo3對象的id依然是1,但因爲上下文對象被重置過,其中的緩存也被清空,因此在第37裏執行的execute方法並無走緩存。
運行上述代碼,咱們能看到以下的輸出,這些打印結果能很好地驗證上述對主要流程的說明。
1 In run 2 the result for cacheDemo1 is:Tom 3 whether get from cache:false 4 the result for cacheDemo2 is:Tom 5 whether get from cache:true 6 In run 7 the result for 3 is:Tom
這裏請你們注意,在緩存相關的getCacheKey方法裏,咱們不是定義「保存緩存值」的邏輯,而是定義「緩存對象的標準」,初學者常常會混淆這點。具體而言,在這裏的getCacheKey方法裏,咱們並無保存id是1的User對象的值(這裏是Tom),而是定義了以下的標準:只要兩個(或多個)HystrixCacheDemo對象具備相同的String.valueOf(id)的值,並且緩存中也已經存有id的1的結果值,那麼後繼對象則能夠直接從緩存裏讀數據。
在上文裏,咱們演示了經過Hystrix調用可用以及不可用服務的運行結果,並在調用過程當中引入了緩存機制,這裏,咱們將在上述案例的基礎上概括Hystrix的通常工做流程。
第一,咱們能夠經過extends HystrixCommand<T>的方式,讓一個類具有Hystrix保護機制的特性,其中T是泛型,在上述案例中咱們用到的是String。
第二,一旦繼承了HystrixCommand以後,咱們就能夠經過重寫run方法和getFallback方法來定義調用「可用」和「不可用」服務的業務功能代碼,其中,這兩個方法的返回值須要和第一步裏定義的泛型T一致。而在項目裏,咱們通常在getFallback方法裏,定義「服務不可用」時的保護措施(也就是後文裏將要提到的降級措施)。
第三,咱們還能夠經過緩存機制來下降併發狀況下對服務器的壓力,在Hystrix裏,咱們能夠在getCacheKey裏定義「判斷能夠走緩存對象的標準」。
在使用緩存是,請注意兩點,第一須要開啓上下文,第二,Hystrix會根據定義在類裏的屬性判斷屢次調用的對象是不是同一個,若是是,並且以前被調用過,則能夠走緩存。
本文謝絕轉載。