服務的升級和降級


1.開關 

        先講一下開關的由來,例如京東在6月18日做店慶促銷活動,在交易下單環節,可能需要調用A、B、C三個接口來完成,但是其實A和B是必須的,C只是附加的功能(例如在下單的時候做一下推薦),可有可無,在平時系統沒有壓力,容量充足的情況下,調用下沒問題但是在類似店慶之類的大促環節,系統已經滿負荷了,這時候其實完全可以不去調用C接口,怎么實現這個呢?改代碼?no,no,no,這樣太不敏捷,此時開關誕生了,開發人員只要簡單執行一下命令或者點一下頁面,就可以關掉對於C接口的調用,在大促過去之后,再把開關恢復回去即可。

 

2.什么是服務降級

          服務降級,當服務器壓力劇增的情況下,根據當前業務情況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。


3.服務降級方式:

 

  • 服務接口拒絕服務:無用戶特定信息,頁面能訪問,但是添加刪除提示服務器繁忙。頁面內容也可在Varnish或CDN內獲取。
  • 頁面拒絕服務:頁面提示由於服務繁忙此服務暫停。跳轉到varnish或nginx的一個靜態頁面。
  •  延遲持久化:頁面訪問照常,但是涉及記錄變更,會提示稍晚能看到結果,將數據記錄到異步隊列或log,服務恢復后執行。
  •  隨機拒絕服務:服務接口隨機拒絕服務,讓用戶重試,目前較少有人采用。因為用戶體驗不佳。

4.

 




5.



6.服務降級埋點的地方:


        消息中間件:所有API調用可以使用消息中間件進行控制
        前端頁面:指定網址不可訪問(NGINX+LUA)

        底層數據驅動:拒絕所有增刪改動作,只允許查詢

轉自:http://blog.csdn.net/zuoanyinxiang/article/details/51027576

 

*************************************************************************************************

伴隨着微服務架構被宣傳得如火如荼,一些概念也被推到了我們面前(管你接受不接受),其實大多數概念以前就有,但很少被提的這么頻繁(現在好像不提及都不好意思交流了)。想起有人總結的一句話,微服務架構的特點就是:“一解釋就懂,一問就不知,一討論就吵架”。

其實對老外的總結能力一直特別崇拜,Kevin Kelly、Martin Fowler、Werner Vogels……,都是著名的“演講家”。正好這段時間看了些微服務、容器的相關資料,也在我們新一代產品中進行了部分實踐,回過頭來,再來談談對一些概念的理解。
 
今天先來說說“服務熔斷”和“服務降級”。為什么要說這個呢,因為我很長時間里都把這兩個概念同質化了,不知道這兩個詞大家怎么理解,一個意思or有所不同?現在的我是這么來看的:
  1. 在股票市場,熔斷這個詞大家都不陌生,是指當股指波幅達到某個點后,交易所為控制風險采取的暫停交易措施。相應的,服務熔斷一般是指軟件系統中,由於某些原因使得服務出現了過載現象,為防止造成整個系統故障,從而采用的一種保護措施,所以很多地方把熔斷亦稱為過載保護。
  2. 大家都見過女生旅行吧,大號的旅行箱是必備物,平常走走近處綽綽有余,但一旦出個遠門,再大的箱子都白搭了,怎么辦呢?常見的情景就是把物品拿出來分分堆,比了又比,最后一些非必需品的就忍痛放下了,等到下次箱子夠用了,再帶上用一用。而服務降級,就是這么回事,整體資源快不夠了,忍痛將某些服務先關掉,待渡過難關,再開啟回來。
所以從上述分析來看,兩者其實從有些角度看是有一定的類似性的:
  1. 目的很一致,都是從可用性可靠性着想,為防止系統的整體緩慢甚至崩潰,采用的技術手段;
  2. 最終表現類似,對於兩者來說,最終讓用戶體驗到的是某些功能暫時不可達或不可用;
  3. 粒度一般都是服務級別,當然,業界也有不少更細粒度的做法,比如做到數據持久層(允許查詢,不允許增刪改);
  4. 自治性要求很高,熔斷模式一般都是服務基於策略的自動觸發,降級雖說可人工干預,但在微服務架構下,完全靠人顯然不可能,開關預置、配置中心都是必要手段;
而兩者的區別也是明顯的:
  1. 觸發原因不太一樣,服務熔斷一般是某個服務(下游服務)故障引起,而服務降級一般是從整體負荷考慮;
  2. 管理目標的層次不太一樣,熔斷其實是一個框架級的處理,每個微服務都需要(無層級之分),而降級一般需要對業務有層級之分(比如降級一般是從最外圍服務開始)
  3. 實現方式不太一樣,這個區別后面會單獨來說;
當然這只是我個人對兩者的理解,外面把兩者歸為完全一致的也不在少數,或者把熔斷機制理解為應對降級目標的一種實現也說的過去,可能“一討論就吵架”也正是這個原因吧!
概念算是說完了,避免空談,我再總結下對常用的實現方法的理解。對於這兩個概念,號稱支持的框架可不少,Hystrix當屬其中的佼佼者。
先說說最裸的熔斷器的設計思路,下面這張圖大家應該不陌生(我只是參考着又畫了畫),簡明扼要的給出了好的熔斷器實現的三個狀態機:

  1. Closed:熔斷器關閉狀態,調用失敗次數積累,到了閾值(或一定比例)則啟動熔斷機制;
  2. Open:熔斷器打開狀態,此時對下游的調用都內部直接返回錯誤,不走網絡,但設計了一個時鍾選項,默認的時鍾達到了一定時間(這個時間一般設置成平均故障處理時間,也就是MTTR),到了這個時間,進入半熔斷狀態;
  3. Half-Open:半熔斷狀態,允許定量的服務請求,如果調用都成功(或一定比例)則認為恢復了,關閉熔斷器,否則認為還沒好,又回到熔斷器打開狀態;
那Hystrix,作為Netflix開源框架中的最受喜愛組件之一,是怎么處理依賴隔離,實現熔斷機制的呢,他的處理遠比我上面說個實現機制復雜的多,一起來看看核心代碼吧,我只保留了代碼片段的關鍵部分:
[java]  view plain  copy
 
  1. public abstract class HystrixCommand<R> extends AbstractCommand<R> implements HystrixExecutable<R>, HystrixInvokableInfo<R>, HystrixObservable<R> {  
  2.   
  3.     protected abstract R run() throws Exception;  
  4.   
  5.     protected R getFallback() {  
  6.         throw new UnsupportedOperationException("No fallback available.");  
  7.     }  
  8.   
  9.     @Override  
  10.     final protected Observable<R> getExecutionObservable() {  
  11.         return Observable.defer(new Func0<Observable<R>>() {  
  12.             @Override  
  13.             public Observable<R> call() {  
  14.                 try {  
  15.                     return Observable.just(run());  
  16.                 } catch (Throwable ex) {  
  17.                     return Observable.error(ex);  
  18.                 }  
  19.             }  
  20.         });  
  21.     }  
  22.   
  23.     @Override  
  24.     final protected Observable<R> getFallbackObservable() {  
  25.         return Observable.defer(new Func0<Observable<R>>() {  
  26.             @Override  
  27.             public Observable<R> call() {  
  28.                 try {  
  29.                     return Observable.just(getFallback());  
  30.                 } catch (Throwable ex) {  
  31.                     return Observable.error(ex);  
  32.                 }  
  33.             }  
  34.         });  
  35.     }  
  36.   
  37.     public R execute() {  
  38.         try {  
  39.             return queue().get();  
  40.         } catch (Exception e) {  
  41.             throw decomposeException(e);  
  42.         }  
  43.     }  
HystrixCommand是重重之重,在Hystrix的整個機制中,涉及到依賴邊界的地方,都是通過這個Command模式進行調用的,顯然,這個Command負責了核心的服務熔斷和降級的處理,子類要實現的方法主要有兩個:
  1. run方法:實現依賴的邏輯,或者說是實現微服務之間的調用;
  2. getFallBack方法:實現服務降級處理邏輯,只做熔斷處理的則可不實現;
使用時,可參考如下方式:
[java]  view plain  copy
 
  1. public class TestCommand extends HystrixCommand<String> {  
  2.   
  3.     protected TestCommand(HystrixCommandGroupKey group) {  
  4.         super(group);  
  5.     }  
  6.   
  7.     @Override  
  8.     protected String run() throws Exception {  
  9.         //這里需要做實際調用邏輯  
  10.         return "Hello";  
  11.     }  
  12.       
  13.     public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {  
  14.         TestCommand command = new TestCommand(HystrixCommandGroupKey.Factory.asKey("TestGroup"));  
  15.           
  16.         //1.這個是同步調用  
  17.         command.execute();  
  18.           
  19.         //2.這個是異步調用  
  20.         command.queue().get(500, TimeUnit.MILLISECONDS);  
  21.           
  22.         //3.異步回調  
  23.         command.observe().subscribe(new Action1<String>() {  
  24.             public void call(String arg0) {  
  25.                   
  26.             }  
  27.         });  
  28.     }  
  29. }  
細心的同學肯定發現Command機制里大量使用了Observable相關的API,這個是什么呢?原來其隸屬於RxJava,這個框架就不多介紹了 --- 響應式開發,也是Netflix的作品之一,具體大家可參考這系列博客,我覺得作者寫的很通俗:http://blog.csdn.net/lzyzsd/article/details/41833541/
接着呢,大家一定會問,那之前說的熔斷閾值設置等,都在哪塊做的呢?再來看看另一塊核心代碼:
[java]  view plain  copy
 
  1. public abstract class HystrixPropertiesStrategy {  
  2.   
  3.     public HystrixCommandProperties getCommandProperties(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {  
  4.         return new HystrixPropertiesCommandDefault(commandKey, builder);  
  5.     }  
  6.   
  7.     ......  
  8. }  
這個類作為策略類,返回相關的屬性配置,大家可重新實現。而在具體的策略中,主要包括以下幾種策略屬性配置:

 

  1. circuitBreakerEnabled:是否允許熔斷,默認允許;
  2. circuitBreakerRequestVolumeThreshold:熔斷器是否開啟的閥值,也就是說單位時間超過了閥值請求數,熔斷器才開;
  3. circuitBreakerSleepWindowInMilliseconds:熔斷器默認工作時間,超過此時間會進入半開狀態,即允許流量做嘗試;
  4. circuitBreakerErrorThresholdPercentage:錯誤比例觸發熔斷;
  5. ......

 

屬性很多,這里就不一一說明了,大家可參考HystrixCommandProperties類里的詳細定義。還有一點要着重說明的,在熔斷器的設計里,隔離采用了線程的方式(據說還有信號的方式,這兩個區別我還沒搞太明白),處理依賴並發和阻塞擴展,示意圖如下:
如上圖,好處也很明顯,對於每個依賴都有獨立可控的線程池,當然高並發時,CPU切換較多,有一定的影響。
啰嗦了一堆,最后總結一下,我認為服務熔斷和服務降級兩者是有區別的,同時通過對Hystrix的簡單學習,了解了其實現機制,會逐步引入到我們的產品研發中。當然還有好多概念:服務限流、分流,請求與依賴分離等,后面有時間一一與大家分享。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM