前言

微服務架構在如今的9102年已經不是什麼新鮮的話題了,但是怎麼做好微服務架構,卻又是一個永恆的話題。比如服務粒度的劃分,怎麼控制好粗細?服務劃分後,對於項目的部署會有什麼改變?… 這會是一個很大的話題,以後可以分開篇章探討一翻,但是我們本篇並不打算聊這個,而是討論一下具體的實現技術–dubbo

dubbo歷史

2011 年末,阿里巴巴在 GitHub 上開源了基於 Java 的分散式服務治理框架 Dubbo,之後它成為了國內該類開源項目的佼佼者,許多開發者對其表示青睞。同時,先後有不少公司在實踐中基於 Dubbo 進行分散式系統架構,目前在 GitHub 上,它的 fork、star 數均已破萬。2014 年 10 月 30 號發布版本 dubbo-2.4.11,修復了一個小 Bug,版本又陷入漫長的停滯到2017年九月份。

在dubbo停滯的期間呢,噹噹網 Fork 了阿里的一個 Dubbo 版本開始維護,並命名為 dubbox-2.8.0。值得注意的是,噹噹網擴展 Dubbo 服務框架支持 REST 風格遠程調用,並且跟隨著 ZooKeepe 和 Spring 升級了對應的版本。之後 Dubbox 一直在小版本維護,2015 年 3 月 31 號發布了最後一個版本 dubbox-2.8.4。筆者公司用的也是這個版本,並稍微改造了下源碼,下面會有提及。

其實在當前說到微服務,可能大家第一反應是springcloud,spring全家桶帶來的便捷是顯而易見的,然而為什麼我們這裡聊的是dubbo呢?原因之一是因為筆者公司只用了dubbo(別扔雞蛋…),其二呢其實rpc框架很多原理是相通的,當我們理解了其中一個,再去看其他的框架,會有一種似曾相識的感覺,最後也沒必要去爭論XX框架的好與壞,選擇最適合自己業務的就是最好的。

先交代下背景,我們這邊是從2016年開始使用dubbo,使用的是dubbox-2.8.4 版本,然後因為一些場景不合適改了下代碼,重新打包成2.8.5提交至公司的私服使用。好了,接下來就開始進入正文,聊聊這幾年在dubbo使用過程中遇到坑,以及需要注意的地方吧。

正文

1、超時重試

這是一個很經典的坑,當時由於剛使用dubbo,很多配置都是基於默認的。剛好此時在項目中,有一個機器人送禮的邏輯比較複雜,當遇到某些特定的條件時,該邏輯的耗時會比正常情況下變長,這時候就出現了一個很神奇的現象,為何我只觸發了一次送禮的請求,而線上卻送了三次?

剛遇到這種情況可我驚呆了,重新審視了代碼,發現並無問題。這就奇怪了,哪裡來的3次?後來掉了幾根頭髮以後,才在dubbo的文檔中發現了服務這塊有timeout跟retry屬性,默認timeout=1000ms,retry=2。這下就豁然開朗,原來是第一次調用超時,導致又重試了2次,一共就是3次了。

找到問題的原因,我們就有辦法解決了。由於我們這個介面不是冪等性的,而且也不用返回什麼信息給調用者,所以我們可以通過一個線程池來執行這段耗時的邏輯,讓rpc調用可以比較快的返回給調用者。這樣就不存在超時的問題了。或者可以配合增加timeout時間跟retry=0也能實現,具體的業務邏輯需要自己找到合適的解決方案。

2、dubbo使用內網ip

正常情況下,我們的服務調用推薦走內網連接的方式,效率是比較高的。但是有些特殊的情況,我們需要dubbo註冊服務的時候使用外網ip,該怎麼修改呢?這時候就需要修改我們的伺服器上 /etc/hosts 文件了,新增一條 「外網ip 主機名」的記錄,restart我們的服務即可。

3、docker裡面註冊宿主機內網ip

說到微服務,當然也少不了docker了,我們當前用的是docker+overlay網路一個結構,直接把dubbo服務丟進容器裡面跑的話,註冊進zk的ip是容器ip。所以我們採取了一種折中的方式。

利用docker的特性,我們在創建容器的時候,把宿主機的ip以及需要暴露的埠寫進容器的環境變數裡面。然後就是修改dubbox的源碼了,源碼的com.alibaba.dubbo.registry.integration.RegistryProtocol類的getRegistedProviderUrl

方法,此方法用於返回註冊到註冊中心的URL。

<pre stylex="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">private URL getRegistedProviderUrl(final Invoker<?> originInvoker){
//targetUrl 註冊中心看到的地址
URL targetUrl;
URL providerUrl = getProviderUrl(originInvoker);
//配置的容器環境變數
String envParameterHost=System.getenv(ENV_HOST_KEY);
String envParameterPort=System.getenv(ENV_PORT_KEY);
if (StringUtils.isBlank(envParameterHost)||StringUtils.isBlank(envParameterPort)){
//非容器環境:執行原來的註冊邏輯
targetUrl=providerUrl.removeParameters(getFilteredKeys(providerUrl)).removeParameter(Constants.MONITOR_KEY);
} else {
//容器環境,如果環境變數中DOCKER_NAT_HOST和DOCKER_NAT_PORT兩個值都不為空則直接將這兩個值作為url註冊到zk
//執行重新拼接url的操作,涉及敏感代碼這裡不展示了
targetUrl=dockerRegUrlWithHostAndPort;
}
return targetUrl;
}
</pre>

4、未注意服務重名

其實這是我們開發人員粗心大意出現的情況,開發的時候註冊了2個相同簽名的服務,但是業務邏輯是完全不同的,這會導致一個之前運行的正常的業務會偶爾調用失敗,原因是因為dubbo的負載均衡策略,把一部分流量轉移到我們新註冊上來的服務上了,但是處理邏輯不同,導致錯誤。

5、版本的一致性

dubbo當前的releases版本已經去到2.7.1了,項目中要注意一下不同項目間版本的一致性,或者是dubbo跟dubbox的一些差別,最好做到統一,不然出現問題解決的成本會比較高。

6、屬性配置的優先順序

我們在dubbo的過程中會發現,提供者跟消費者中,很多屬性是一樣的,我們該怎麼配呢?在dubbo的文檔當中其實有推薦的用法。

在提供者端盡量多提供消費者端的屬性。

參考文檔,原因如下:

作服務的提供方,比服務消費方更清楚服務的性能參數,如調用的超時時間、合理的重試次數等

在 Provider 端配置後,Consumer 端不配置則會使用 Provider 端的配置,即 Provider 端的配置可以作為Consumer 的預設值 。否則,Consumer 會使用 Consumer 端的全局設置,這對於 Provider是不可控的,並且往往是不合理的

Provider 端盡量多配置 Consumer 端的屬性,讓 Provider 的實現者一開始就思考 Provider 端的服務特點和服務質量等問題。

結語

其實在dubbo的使用過程中,還有挺多問題這裡沒列出來的,但是解決方法都差不多,首先文檔要熟,做到心中有數,比如dubbo功能的成熟度,有些是不推薦在線上使用的,這時你就要謹慎了。然後文檔裡面確實是有遺漏的問題,我們有必要可以debug dubbo的源碼,這個過程會比較痛苦,但是對於排查問題跟個人能力的提高是有很有幫助的。


文末彩蛋

針對於上面涉及到的知識點我總結出了有1到5年開發經驗的程序員在面試中涉及到的絕大部分架構面試題及答案做成了文檔和架構視頻資料免費分享給大家(包括Dubbo、Redis、Netty、zookeeper、Spring cloud、分散式、高並發等架構技術資料),希望能幫助到您面試前的複習且找到一個好的工作,也節省大家在網上搜索資料的時間來學習,也可以關注我一下以後會有更多乾貨分享。

喜歡這篇文章的可以點個贊,也可以關注我的專欄 java經驗分享 ,專欄頂部有免費獲取資料方式


推薦閱讀:
相关文章