dubbo源码解析-逻辑层设计之服务降级
Dubbo源碼解析系列文章均來自肥朝簡(jiǎn)書
前言
在dubbo服務(wù)暴露系列完結(jié)之后,按計(jì)劃來說是應(yīng)該要開啟dubbo服務(wù)引用的講解.但是現(xiàn)在到了年尾,一些朋友也和我談起了明年跳槽的事.跳槽這件事,無非也就兩個(gè)原因,一個(gè)是錢沒給夠,另一個(gè)是心里委屈了.首先錢沒給夠這件事我就不多說什么了,因?yàn)槊總€(gè)人都覺得自己錢沒給夠.那心里為啥委屈了?作為一個(gè)技術(shù)人,我認(rèn)為心里委屈,無非也就是兩個(gè)原因,一個(gè)是在公司得不到重視,另一個(gè)是感覺學(xué)不到東西,得不到成長(zhǎng).感覺我所了解到的情況,往往是后者居多.這道理也簡(jiǎn)單,我們小時(shí)候看重的是興趣和愛好,長(zhǎng)大后看重的是投資和回報(bào).
互聯(lián)網(wǎng)行業(yè)加班是常態(tài),首先我不反對(duì)加班.但是加班帶來的影響也不得不重視.首先對(duì)于老板而言,員工加班越多,獲得的利潤(rùn)更大.比如:
我們老板來上班事開了一輛嶄新的蘭博基尼。
我說:“哇喔,這輛車好牛逼”
他回答:“如果你努力工作,全身心投入,力求卓越,那么我明年還會(huì)再有一輛”。
再次,一旦你加班多了,學(xué)習(xí)新技術(shù)的時(shí)間就少,這樣你就會(huì)變得越來越不自信,自然不敢隨便跳槽.但是加班和學(xué)習(xí)其實(shí)并不沖突.即使加班再多(比如今天周六我也還在加班),肥朝每周一篇dubbo源碼解析與你不見不散,請(qǐng)放心保持密切關(guān)注肥朝.
如果你是因?yàn)閷W(xué)不到東西跳槽,那么往往會(huì)遇到一個(gè)問題,那就是公司的項(xiàng)目太low,找一下家的時(shí)候拿不出手.技術(shù)上,增刪改查這種東西肯定是拿不出手的,我用freemarker + mybatis generator做代碼生成器直接一鍵生成就可以直接運(yùn)行跑起來.業(yè)務(wù)上,每個(gè)公司的業(yè)務(wù)都不同,討論意義不大.想去網(wǎng)上找點(diǎn)資料裝逼,但是卻發(fā)現(xiàn)無從下手.好不容易找了點(diǎn)技術(shù)沙龍逼格高的PPT,不幸的是都是空談理論,無法和自己公司的項(xiàng)目銜接起來.但是幸運(yùn)的是無意中關(guān)注了肥朝.
首先我們來看看,我在三張圖看清項(xiàng)目結(jié)構(gòu)提到的中小型公司比較典型的Java項(xiàng)目的架構(gòu).
從中可以看出,典型的就是三層結(jié)構(gòu),
- 接入層,邏輯層,數(shù)據(jù)存儲(chǔ)層.
當(dāng)然也可以分成四層
- 接入層,邏輯層,原子服務(wù)層,數(shù)據(jù)存儲(chǔ)層.
當(dāng)然是可以分成五層
- 接入層,序列化層(異步消息隊(duì)列),原子服務(wù)層,數(shù)據(jù)層,數(shù)據(jù)存儲(chǔ)層.
當(dāng)然分幾層都要根據(jù)自身業(yè)務(wù),好的架構(gòu)并不是一蹴而就,而是逐漸演變的過程.從標(biāo)題就可以知道,本篇著重介紹邏輯層的設(shè)計(jì)(那剩下的什么時(shí)候講?反正每周一篇,一年也就48篇.dubbo系列完結(jié)之后下一個(gè)系列由你來定,你可以自己估算一下時(shí)間).既然是設(shè)計(jì),那么就不能紙上談兵,必須站在巨人的肩膀上,比如孫玄老師分享的58同城架構(gòu)設(shè)計(jì)就很有參考意義.我簡(jiǎn)單用思維導(dǎo)圖做了個(gè)總結(jié).如下:
看到這里有朋友可能就不樂意了,不要扯這些原則,老子拿起鍵盤就是干.
我想說的是,如果沒有讀萬卷書,即使行了萬里路,也不過是個(gè)郵差.知道了理論,下面我們直入主題,開始實(shí)戰(zhàn).
插播面試題
-
談一下你們項(xiàng)目架構(gòu)設(shè)計(jì)(很多人在回答這個(gè)的時(shí)候都容易回答SSH或者SSM,注意,所謂是SSH這些是技術(shù)選型,不是架構(gòu)的設(shè)計(jì))
-
既然你們項(xiàng)目用到了dubbo,那你講講你們是怎么通過dubbo實(shí)現(xiàn)服務(wù)降級(jí)的,降級(jí)的方式有哪些,又有什么區(qū)別?
-
dubbo監(jiān)控平臺(tái)能夠動(dòng)態(tài)改變接口的一些設(shè)置,其原理是怎樣的?
-
既然你說你看過dubbo源碼,那講一下有沒有遇到過什么坑?(區(qū)分度高,也是檢驗(yàn)是否看過源碼的試金石)
直入主題
我們從兩個(gè)角度來分析,一個(gè)是為什么需要服務(wù)降級(jí),一個(gè)是怎么做服務(wù)降級(jí)
為什么需要服務(wù)降級(jí)
引進(jìn)一個(gè)新技術(shù),必須要看這個(gè)新技術(shù)解決了什么問題.比如服務(wù)降級(jí),他解決了什么問題?從上面的思維導(dǎo)圖我們就知道,當(dāng)網(wǎng)站處于高峰期時(shí),并發(fā)量大,服務(wù)能力有限,那么我們只能暫時(shí)屏蔽邊緣業(yè)務(wù).那么具體的例子是什么?
比如在某寶某東購(gòu)物,當(dāng)支付完成,會(huì)向你推薦一些商品.但是在11大促中,并發(fā)量過大.我們就要保證"支付"這些核心業(yè)務(wù)的正常運(yùn)行,因此像"推薦商品"這些邊緣業(yè)務(wù),我們就可以不調(diào)用,從而減少一定的并發(fā).但是如果雙11我先把"推薦商品"接口的代碼屏蔽起來,等過后我再打開.這種太簡(jiǎn)單粗暴的方法肯定不是我們的理想追求,這時(shí)候我們就需要一個(gè)"服務(wù)開關(guān)"一樣的東西.這個(gè)開關(guān),就是服務(wù)降級(jí)
怎么做服務(wù)降級(jí)
空談?wù)`國(guó),實(shí)戰(zhàn)興邦,光知道思維導(dǎo)圖上的這些設(shè)計(jì)原則還不行,我們以dubbo為例,實(shí)戰(zhàn)一下服務(wù)降級(jí).首先dubbo中的服務(wù)降級(jí)分成兩個(gè)
-
屏蔽(mock=force)
-
容錯(cuò)(mock=fail)
這兩個(gè)有什么區(qū)別呢?我們引用文檔介紹
mock=force:return+null 表示消費(fèi)方對(duì)該服務(wù)的方法調(diào)用都直接返回 null 值,不發(fā)起遠(yuǎn)程調(diào)用。用來屏蔽不重要服務(wù)不可用時(shí)對(duì)調(diào)用方的影響。
還可以改為 mock=fail:return+null 表示消費(fèi)方對(duì)該服務(wù)的方法調(diào)用在失敗后,再返回 null 值,不拋異常。用來容忍不重要服務(wù)不穩(wěn)定時(shí)對(duì)調(diào)用方的影響。
那么下面分別演示一下容錯(cuò)的使用方法
首先我們打上斷點(diǎn),造成請(qǐng)求超時(shí),報(bào)錯(cuò)如下
配置容錯(cuò)
報(bào)錯(cuò)信息立刻消除,結(jié)果如下
屏蔽就不在演示,配置方式類似,效果自己調(diào)試.
其實(shí)從文檔介紹我們就能回答出兩者的區(qū)別.但是老司機(jī)可能更享受的是扒光原理的快感.
源碼分析
首先我假設(shè)你之前看過肥朝每周一篇dubbo源碼解析,那么對(duì)MockClusterInvoker這個(gè)類就不會(huì)陌生,那么我們直接看核心代碼(應(yīng)群友反饋,嘗試一下代碼不貼圖)
從no mock(正常情況),force:direct mock(屏蔽),fail-mock(容錯(cuò))三種情況我們也可以看出,普通情況是直接調(diào)用,容錯(cuò)的情況是調(diào)用失敗后,返回一個(gè)設(shè)置的值.而屏蔽就很暴力了,直接連調(diào)用都不調(diào)用,就直接返回一個(gè)之前設(shè)置的值.
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 mockresult = 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 mockresult = doMockInvoke(invocation, null);} else {//fail-mocktry {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; }敲黑板畫重點(diǎn)
有句話叫盡信書不如無書,dubbo中也難免存在一些bug,比如我之前在dubbo源碼解析-router就提到過,這個(gè)監(jiān)控平臺(tái)是有bug的,如今又出現(xiàn)了
你會(huì)發(fā)現(xiàn)點(diǎn)刪除或者點(diǎn)啟用和禁用后,會(huì)出現(xiàn)多條.解決辦法還是和之前一樣.清除zookeeper上的節(jié)點(diǎn)信息(不懂的可以點(diǎn)回去看看router這篇,這就是我之前反復(fù)強(qiáng)調(diào)的,一定要系統(tǒng)學(xué)習(xí),因?yàn)橹疤岬降奈彝还P帶過)
從這個(gè)解決bug中,我們也應(yīng)該有一些逆向思維.為什么這個(gè)監(jiān)控平臺(tái)這么神奇,能動(dòng)態(tài)改變接口的一些默認(rèn)設(shè)置?你清除了zookeeper節(jié)點(diǎn),監(jiān)控平臺(tái)上的一些配置信息就消失了,很明顯,他這個(gè)原理就是改變注冊(cè)在zookeeper上的節(jié)點(diǎn)信息.從而zookeeper通知重新生成invoker(這些具體細(xì)節(jié)在zookeeper創(chuàng)建節(jié)點(diǎn),zookeeper連接,zookeeper訂閱中都詳細(xì)講了,這里不再重復(fù))
當(dāng)然除了這些坑外,dubbo在集群容錯(cuò)算法中的輪詢就有個(gè)坑,需要調(diào)節(jié)當(dāng)前時(shí)間解決(因?yàn)檫@個(gè)使用不多,這里暫時(shí)不細(xì)說),但是當(dāng)當(dāng)網(wǎng)的dubbox有一個(gè)坑就比較明顯.如下圖,當(dāng)你傳的參數(shù)為null時(shí),這里就有很明顯的空指針
在后面當(dāng)當(dāng)網(wǎng)也解決了這個(gè)問題
當(dāng)然他這個(gè)修復(fù)的代碼也可以出一個(gè)面試題.當(dāng)然這道題我就不解答了
java中 || 和 | 有什么區(qū)別
把握重點(diǎn)
看到這里你就必須要把握一下重點(diǎn).從標(biāo)題你就知道,本篇是有三個(gè)關(guān)鍵詞,分別是dubbo,邏輯層設(shè)計(jì),服務(wù)降級(jí)
我用dubbo演示一種服務(wù)降級(jí)的方式,并不代表是只有這一種方式,你如果仔細(xì)看思維導(dǎo)圖就明白,其實(shí)也還有很多實(shí)現(xiàn)方式.另外如果你覺得你們項(xiàng)目比較low,那么你可以設(shè)想,假如用思維導(dǎo)圖的這些原則來設(shè)計(jì),那么要怎么設(shè)計(jì),有什么優(yōu)缺點(diǎn)?然后自己嘗試改造一下,這思考和行動(dòng)的過程,才是你最寶貴的收獲,也是我想傳達(dá)的學(xué)習(xí)思想.如果你把重點(diǎn)當(dāng)成了dubbo如何配置服務(wù)降級(jí),那么可能再好的項(xiàng)目,你都只看到了增刪改查.
寫在最后
寫到這里的時(shí)候,不知不覺已經(jīng)是凌晨四點(diǎn).因?yàn)?96的模式下,要堅(jiān)持每周一篇對(duì)我來說也是一個(gè)挑戰(zhàn),但是同時(shí)我也享受著這種挑戰(zhàn)的感覺.每次下班的時(shí)候,遇到熟人都會(huì)問我怎么這么晚才下班,加班這么多,一定很多加班費(fèi)吧.我說,沒有加班費(fèi),這個(gè)時(shí)候都會(huì)很自然的反駁到,沒有加班費(fèi)那干嘛加班.同樣的道理,一些朋友看到我寫博客,也會(huì)問,你每周都堅(jiān)持寫博客有錢賺嗎,我說沒有,這個(gè)時(shí)候正常的邏輯也是反駁到,沒有錢干嘛要做.其實(shí)有時(shí)候,博客既是寫給別人看的,也是寫給自己看的.最重要的是從一件事上,看到一個(gè)人做事的決心
?
總結(jié)
以上是生活随笔為你收集整理的dubbo源码解析-逻辑层设计之服务降级的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。