歡迎光臨
每天分享高質量文章

Dubbo原始碼解析 —— 邏輯層設計之服務降級

作者:肥朝
原文地址:https://www.jianshu.com/p/302af7836a59

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

友情提示:歡迎關註公眾號【芋道原始碼】。?關註後,拉你進【原始碼圈】微信群和【肥朝】搞基嗨皮。

前言

dubbo服務暴露系列完結之後,按計劃來說是應該要開啟dubbo服務取用的講解.但是現在到了年尾,一些朋友也和我談起了明年跳槽的事.跳槽這件事,無非也就兩個原因,一個是錢沒給夠,另一個是心裡委屈了.首先錢沒給夠這件事我就不多說什麼了,因為每個人都覺得自己錢沒給夠.那心裡為啥委屈了?作為一個技術人,我認為心裡委屈,無非也就是兩個原因,一個是在公司得不到重視,另一個是感覺學不到東西,得不到成長.感覺我所瞭解到的情況,往往是後者居多.這道理也簡單,我們小時候看重的是興趣和愛好,長大後看重的是投資和回報.

互聯網行業加班是常態,首先我不反對加班.但是加班帶來的影響也不得不重視.首先對於老闆而言,員工加班越多,獲得的利潤更大.比如:

我們老闆來上班事開了一輛嶄新的蘭博基尼。
我說:“哇喔,這輛車好牛逼”
他回答:“如果你努力工作,全身心投入,力求卓越,那麼我明年還會再有一輛”。

再次,一旦你加班多了,學習新技術的時間就少,這樣你就會變得越來越不自信,自然不敢隨便跳槽.但是加班和學習其實並不衝突.即使加班再多(比如今天周六我也還在加班),肥朝每周一篇dubbo原始碼解析與你不見不散,請放心保持密切關註肥朝.

如果你是因為學不到東西跳槽,那麼往往會遇到一個問題,那就是公司的專案太low,找一下家的時候拿不出手.技術上,增刪改查這種東西肯定是拿不出手的,我用freemarker + mybatis generator做代碼生成器直接一鍵生成就可以直接運行跑起來.業務上,每個公司的業務都不同,討論意義不大.想去網上找點資料裝逼,但是卻發現無從下手.好不容易找了點技術沙龍逼格高的PPT,不幸的是都是空談理論,無法和自己公司的專案銜接起來.但是幸運的是無意中關註了肥朝.

首先我們來看看,我在三張圖看清專案結構提到的中小型公司比較典型的Java專案的架構.

從中可以看出,典型的就是三層結構,

  • 接入層,邏輯層,資料儲存層.

當然也可以分成四層

  • 接入層,邏輯層,原子服務層,資料儲存層.

當然是可以分成五層

  • 接入層,序列化層(異步訊息佇列),原子服務層,資料層,資料儲存層.

當然分幾層都要根據自身業務,好的架構並不是一蹴而就,而是逐漸演變的過程.從標題就可以知道,本篇著重介紹邏輯層的設計(那剩下的什麼時候講?反正每周一篇,一年也就48篇.dubbo系列完結之後下一個系列由你來定,你可以自己估算一下時間).既然是設計,那麼就不能紙上談兵,必須站在巨人的肩膀上,比如孫玄老師分享的58同城架構設計就很有參考意義.我簡單用思維導圖做了個總結.如下:

看到這裡有朋友可能就不樂意了,不要扯這些原則,老子拿起鍵盤就是乾.

我想說的是,如果沒有讀萬卷書,即使行了萬里路,也不過是個郵差.知道了理論,下麵我們直入主題,開始實戰.

插播面試題

  • 談一下你們專案架構設計(很多人在回答這個的時候都容易回答SSH或者SSM,註意,所謂是SSH這些是技術選型,不是架構的設計)

  • 既然你們專案用到了dubbo,那你講講你們是怎麼通過dubbo實現服務降級的,降級的方式有哪些,又有什麼區別?

  • dubbo監控平臺能夠動態改變接口的一些設置,其原理是怎樣的?

  • 既然你說你看過dubbo原始碼,那講一下有沒有遇到過什麼坑?(區分度高,也是檢驗是否看過原始碼的試金石)

直入主題

我們從兩個角度來分析,一個是為什麼需要服務降級,一個是怎麼做服務降級

為什麼需要服務降級

引進一個新技術,必須要看這個新技術解決了什麼問題.比如服務降級,他解決了什麼問題?從上面的思維導圖我們就知道,當網站處於高峰期時,併發量大,服務能力有限,那麼我們只能暫時屏蔽邊緣業務.那麼具體的例子是什麼?

比如在某寶某東購物,當支付完成,會向你推薦一些商品.但是在11大促中,併發量過大.我們就要保證”支付”這些核心業務的正常運行,因此像”推薦商品”這些邊緣業務,我們就可以不呼叫,從而減少一定的併發.但是如果雙11我先把”推薦商品”接口的代碼屏蔽起來,等過後我再打開.這種太簡單粗暴的方法肯定不是我們的理想追求,這時候我們就需要一個”服務開關”一樣的東西.這個開關,就是服務降級

怎麼做服務降級

空談誤國,實戰興邦,光知道思維導圖上的這些設計原則還不行,我們以dubbo為例,實戰一下服務降級.首先dubbo中的服務降級分成兩個

  • 屏蔽(mock=force)

  • 容錯(mock=fail)

這兩個有什麼區別呢?我們取用文件介紹

mock=force:return+null 表示消費方對該服務的方法呼叫都直接傳回 null 值,不發起遠程呼叫。用來屏蔽不重要服務不可用時對呼叫方的影響。

還可以改為 mock=fail:return+null 表示消費方對該服務的方法呼叫在失敗後,再傳回 null 值,不拋異常。用來容忍不重要服務不穩定時對呼叫方的影響。

那麼下麵分別演示一下容錯的使用方法

首先我們打上斷點,造成請求超時,報錯如下

配置容錯

報錯信息立刻消除,結果如下

屏蔽就不在演示,配置方式類似,效果自己除錯.

其實從文件介紹我們就能回答出兩者的區別.但是老司機可能更享受的是扒光原理的快感.

原始碼分析

首先我假設你之前看過肥朝每周一篇dubbo原始碼解析,那麼對MockClusterInvoker這個類就不會陌生,那麼我們直接看核心代碼(應群友反饋,嘗試一下代碼不貼圖)

no mock(正常情況),force:direct mock(屏蔽),fail-mock(容錯)三種情況我們也可以看出,普通情況是直接呼叫,容錯的情況是呼叫失敗後,傳回一個設置的值.而屏蔽就很暴力了,直接連呼叫都不呼叫,就直接傳回一個之前設置的值.

public Result invoke(Invocation invocation) throws RpcException {
   Result result = null;
   String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), Constants.MOCK_KEY, Boolean.FALSE.toString()).trim();
   if (value.length() == 0 || value.equalsIgnoreCase("false")){
       //no mock
       result = this.invoker.invoke(invocation);
   } else if (value.startsWith("force")) {
       if (logger.isWarnEnabled()) {
           logger.info("force-mock: " + invocation.getMethodName() + " force-mock enabled , url : " +  directory.getUrl());
       }
       //force:direct mock
       result = doMockInvoke(invocation, null);
   } else {
       //fail-mock
       try {
           result = this.invoker.invoke(invocation);
       }catch (RpcException e) {
           if (e.isBiz()) {
               throw e;
           } else {
               if (logger.isWarnEnabled()) {
                   logger.info("fail-mock: " + invocation.getMethodName() + " fail-mock enabled , url : " +  directory.getUrl(), e);
               }
               result = doMockInvoke(invocation, e);
           }
       }
   }
   return result;
}

敲黑板畫重點

有句話叫盡信書不如無書,dubbo中也難免存在一些bug,比如我之前在dubbo原始碼解析-router就提到過,這個監控平臺是有bug的,如今又出現了

你會發現點刪除或者點啟用和禁用後,會出現多條.解決辦法還是和之前一樣.清除zookeeper上的節點信息(不懂的可以點回去看看router這篇,這就是我之前反覆強調的,一定要系統學習,因為之前提到的我往往一筆帶過)

從這個解決bug中,我們也應該有一些逆向思維.為什麼這個監控平臺這麼神奇,能動態改變接口的一些預設設置?你清除了zookeeper節點,監控平臺上的一些配置信息就消失了,很明顯,他這個原理就是改變註冊在zookeeper上的節點信息.從而zookeeper通知重新生成invoker(這些具體細節在zookeeper創建節點,zookeeper連接,zookeeper訂閱中都詳細講了,這裡不再重覆)

當然除了這些坑外,dubbo在集群容錯演算法中的輪詢就有個坑,需要調節當前時間解決(因為這個使用不多,這裡暫時不細說),但是噹噹網的dubbox有一個坑就比較明顯.如下圖,當你傳的引數為null時,這裡就有很明顯的空指標

在後面噹噹網也解決了這個問題

當然他這個修複的代碼也可以出一個面試題.當然這道題我就不解答了

java中 || 和 | 有什麼區別

把握重點

看到這裡你就必須要把握一下重點.從標題你就知道,本篇是有三個關鍵詞,分別是dubbo,邏輯層設計,服務降級

我用dubbo演示一種服務降級的方式,並不代表是只有這一種方式,你如果仔細看思維導圖就明白,其實也還有很多實現方式.另外如果你覺得你們專案比較low,那麼你可以設想,假如用思維導圖的這些原則來設計,那麼要怎麼設計,有什麼優缺點?然後自己嘗試改造一下,這思考和行動的過程,才是你最寶貴的收穫,也是我想傳達的學習思想.如果你把重點當成了dubbo如何配置服務降級,那麼可能再好的專案,你都只看到了增刪改查.

寫在最後

寫到這裡的時候,不知不覺已經是凌晨四點.因為996的樣式下,要堅持每周一篇對我來說也是一個挑戰,但是同時我也享受著這種挑戰的感覺.每次下班的時候,遇到熟人都會問我怎麼這麼晚才下班,加班這麼多,一定很多加班費吧.我說,沒有加班費,這個時候都會很自然的反駁到,沒有加班費那幹嘛加班.同樣的道理,一些朋友看到我寫博客,也會問,你每周都堅持寫博客有錢賺嗎,我說沒有,這個時候正常的邏輯也是反駁到,沒有錢幹嘛要做.其實有時候,博客既是寫給別人看的,也是寫給自己看的.最重要的是從一件事上,看到一個人做事的決心

期待下周與你相遇.鑒於本人才疏學淺,不對的地方還望斧正,也歡迎關註我的簡書,名稱為肥朝

赞(0)

分享創造快樂