啟動Dubbo項目注冊Zookeeper時提示zookeeper not connected異常原理解析

原創/朱季謙

遇到一個很詭異的問題,我在啟動多個配置相同zookeeper的Dubbo項目時,其他項目都是正常啟動,唯獨有一個項目在啟動過程中,Dubbo注冊zookeeper協議時,竟然出現了這樣的異常提示——

Caused by: java.lang.IllegalStateException: zookeeper not connectedat org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.<init>(CuratorZookeeperClient.java:80)... 79 common frames omitted

我愣了一下,原以為是zookeeper集群掛了,然后檢查了一下,都正常啊,奇怪的是,其他系統也是正常連接,為啥會有一臺出現了這樣的異常呢?

看了一下異常提示,當我深入研究了一下出錯的地方時,才恍然明白出現這個異常究竟是為什么了。

可謂是,在源碼面前,一切都是裸泳。

先來看異常提示出現的類方法CuratorZookeeperClient,這個方法的作用是建立zookeeper客戶端的連接,類似http通信一般,在建立通信前,需要先建立三次握手連接,同理,在zookeeper客戶端創建各類節點前,同樣需要先建立客戶端連接到服務器上——

 public CuratorZookeeperClient(URL url) {super(url);try {int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS);int sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS);CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder().connectString(url.getBackupAddress()).retryPolicy(new RetryNTimes(1, 1000)).connectionTimeoutMs(timeout).sessionTimeoutMs(sessionExpireMs);String authority = url.getAuthority();if (authority != null && authority.length() > 0) {builder = builder.authorization("digest", authority.getBytes());}client = builder.build();client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url));client.start();boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS);if (!connected) {throw new IllegalStateException("zookeeper not connected");}} catch (Exception e) {throw new IllegalStateException(e.getMessage(), e);}}

根據CuratorZookeeperClient方法可知,出現zookeeper not connected異常提示是發生在這一段代碼當中——

if (!connected) {throw new IllegalStateException("zookeeper not connected");
}

connected表示連接狀態,當它的值為false時,便會執行這段代碼,那么,究竟是什么情況會導致它的值為false呢?

接下來,讓我們打一個斷點,一步一步解析這段代碼。

首先,用作測試的dubbo和zookeeper配置如下——

dubbo:application:name: testerviceregistry:address: zookeeper://120.77.217.245
#    timeout: 20000protocol:name: dubboport: 20880

解析來,開始debug,打斷點,CuratorZookeeperClient方法參數url主要包含以下信息——
?

image


第一步、從url中獲取超時時間timeout參數——

int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS);

這里的大概邏輯是,如果yaml配置registry注冊zookeeper部分參數當中含有 timeout話,那么就返回配置當中定義的超時時間,如果yaml沒有進行配置,那么,就用默認的超時時間,默認即常量DEFAULT_CONNECTION_TIMEOUT_MS,值是5 * 1000,也就是5秒,這個參數其實就是本篇文章的核心。

若自定義形式配置該參數,形式如下timeout: 20000——

dubbo:application:name: testerviceregistry:address: zookeeper://120.77.217.245timeout: 20000

第二步、獲取客戶端過期時間——

 int sessionExpireMs = url.getParameter(ZK_SESSION_EXPIRE_KEY, DEFAULT_SESSION_TIMEOUT_MS);

同理,無自定義配置話,則使用默認值DEFAULT_SESSION_TIMEOUT_MS = 60 * 1000,即6分鐘;

第三步、創建一個設置過期時間為6分鐘,連接超時為5秒,重試策略為每秒重試一次,連接服務端為url.getBackupAddress()(注:我這里得到的是120.77.217.245:9090,即配置的zookeeper連接url)的CuratorFramework客戶端實例——

CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder().connectString(url.getBackupAddress()).retryPolicy(new RetryNTimes(1, 1000)).connectionTimeoutMs(timeout).sessionTimeoutMs(sessionExpireMs);
client = builder.build();

第四步、添加連接狀態的監控,可以監控操作節點與連接情況——

client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url));

第五步、開啟客戶端——

client.start();

最后一步,監控客戶端連接情況,若能連接成功,則證明創建客戶端成功,反之,失敗。可見,若出現zookeeper not connected,問題就在于客戶端連接過程是失敗的,至于為何失敗,原理就在client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS)代碼里。

 boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS);
if (!connected) {throw new IllegalStateException("zookeeper not connected");
}

進入到 client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS)源碼里,這里的maxWaitTime即前邊的timeout,默認值是5秒,大概分析一下下邊代碼——

public synchronized boolean blockUntilConnected(int maxWaitTime, TimeUnit units) throws InterruptedException
{//獲取當前時間long startTime = System.currentTimeMillis();//這里是trueboolean hasMaxWait = (units != null);//maxWaitTimeMs等于5000毫秒,即5秒long maxWaitTimeMs = hasMaxWait ? TimeUnit.MILLISECONDS.convert(maxWaitTime, units) : 0;while ( !isConnected() ){//hasMaxWait為trueif ( hasMaxWait ){   //倒數5秒long waitTime = maxWaitTimeMs - (System.currentTimeMillis() - startTime);//執行到這里,已經過去5秒話,就執行以下方法,返回isConnected()值if ( waitTime <= 0 ){return isConnected();}//還沒到5秒話,假如執行到這里還有3秒,那么就會執行Object.wait(long timeout)方法,即該線程阻塞3秒后再自動喚醒,接著繼續執行wait(waitTime);}else{wait();}}return isConnected();
}

該方法的核心會等待maxWaitTime時間,時間一到,就會返回isConnected()值,這里其實很好理解,就是客戶端發起連接后,這里用一個while循環來等待指定的超時時間,默認是5秒,若5秒過了,就返回isConnected()值,而這里的isConnected()就是驗證是否連接成功了,

那么,這里就剩最后一個答案了,isConnected()是什么?

public synchronized boolean isConnected(){return (currentConnectionState != null) && currentConnectionState.isConnected();
}

這里應該是判斷客戶端連接狀態,即在client.start()方法里,會有一個狀態,若創建連接成功,那么currentConnectionState.isConnected()就能得到true值,這里更像是一個觀察模式,觀察指定的連接超時時間內,是否連接成功。

根據debug,發現未連接成功時,值是null,得到的即為false,當我們把默認為5秒的連接超時設置為timeout: 20000,等待連接過程,發現連接成功了,返回currentConnectionState的值為RECONNECTED。

可見,之前出現zookeeper not connected異常問題,就是連接超時設置太短了!
?

image


currentConnectionState.isConnected()得到的是一個枚舉值,RECONNECTED返回的是true——

  CONNECTED {public boolean isConnected() {return true;}},SUSPENDED {public boolean isConnected() {return false;}},RECONNECTED {public boolean isConnected() {return true;}},LOST {public boolean isConnected() {return false;}},READ_ONLY {public boolean isConnected() {return true;}};

當返回true話,那么!connected就為false,就不會執行以下異常提示了——

if (!connected) {throw new IllegalStateException("zookeeper not connected");
}

根據上邊分析,可見啟動Dubbo項目注冊Zookeeper時提示zookeeper not connected異常,是因為沒有在配置里設置連接超時,而是使用了默認的5秒,導致5秒內沒有成功連接,就出現連接異常而無法成功連接,當調長時間后,就正常連接成功了,同時也說明了,這次本地連接zookeeper集群的時間超過了五秒。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/161154.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161154.shtml
英文地址,請注明出處:http://en.pswp.cn/news/161154.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenAI再次與Sam Altman談判;ChatGPT Voice正式上線

11月22日&#xff0c;金融時報消息&#xff0c;OpenAI迫于超過700名員工聯名信的壓力&#xff0c;再次啟動了與Sam Altman的談判&#xff0c;希望他回歸董事會。 在Sam確定加入微軟后&#xff0c;OpenAI超700名員工簽署了一封聯名信&#xff0c;要求Sam和Greg Brockman&#x…

【尚硅谷】第06章:隨堂復習與企業真題(面向對象-基礎)

第06章&#xff1a;隨堂復習與企業真題&#xff08;面向對象-基礎&#xff09; 一、隨堂復習 1. &#xff08;了解&#xff09;面向過程 vs 面向對象 不管是面向過程、面向對象&#xff0c;都是程序設計的思路。面向過程&#xff1a;以函數為基本單位&#xff0c;適合解決簡單…

解決ElementUI時間選擇器回顯出現Wed..2013..中國標準時間.

使用餓了么組件 時間日期選擇框回顯到頁面為啥是這樣的&#xff1f; 為什么再時間框中選擇日期&#xff0c;回顯頁面出現了這種英文格式呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; 其實這個問題直接使用elementui的內置屬性就能解決 DateTimePicker 日期時間選擇…

程序員指南六:數據平面開發套件

PORT HOTPLUG FRAMEWORK 端口熱插拔框架為DPDK應用程序提供在運行時附加和分離端口的能力。由于該框架依賴于PMD實現&#xff0c;PMD無法處理的端口超出了該框架的范圍。此外&#xff0c;在從DPDK應用程序分離端口后&#xff0c;該框架不提供從系統中移除設備的方法。對于由物…

微信開發:API接口與ipad協議的深度比較及最佳選擇

微信開發&#xff1a;API接口與ipad協議的深度比較及最佳選擇 在深入探索微信開發的過程中&#xff0c;理解不同API接口和協議的特點以及他們的適用場景是非常重要的。本文將詳細對比幾種主流的微信API接口和協議&#xff0c;包括Web版微信協議、iPad協議、PC微信協議/Mac協議…

opencv-圖像梯度

目標 ? 圖像梯度&#xff0c;圖像邊界等 ? 使用到的函數有&#xff1a;cv2.Sobel()&#xff0c;cv2.Schar()&#xff0c;cv2.Laplacian() 等 原理 梯度簡單來說就是求導。 OpenCV 提供了三種不同的梯度濾波器&#xff0c;或者說高通濾波器&#xff1a;Sobel&#xff0c;Schar…

萬界星空科技QMS質量管理系統介紹

QMS&#xff08;Quality Management System&#xff09;質量管理系統是五大基礎系統之一&#xff0c;在工業企業中被廣泛的應用&#xff0c;在質量策劃、生產過程質量監督、體系審核和文檔管理等業務上發揮著不可替代的作用。 一般制造業工廠現狀&#xff1a;質量成本高&#x…

使用 COPY 加速 PostgreSQL 批量插入

文章目錄 1.copy命令介紹2.copy vs insert的優勢3.測量性能4.結論 1.copy命令介紹 PostgreSQL 中的命令COPY是執行批量插入和數據遷移的強大工具。它允許快速有效地將大量數據插入表中。 COPY命令為批量插入和數據遷移提供了更簡單且更具成本效益的解決方案。 可以避免使用諸…

基于SSM的課程資源管理系統

末尾獲取源碼 開發語言&#xff1a;Java Java開發工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技術開發 數據庫&#xff1a;MySQL5.7和Navicat管理工具結合 服務器&#xff1a;Tomcat8.5 開發軟件&#xff1a;IDEA / Eclipse 是否Maven項目&#x…

電力感知邊緣計算網關產品設計方案-網關系統通信架構方案

1.邊緣協同控制模發 能針對建筑、充電樁、分布式儲能、分布式光伏等典型設備建立對應物模型、完成數據采集通信協議設計和控制指令交互設計,能針對建筑、充換電站等典型場景提出具體實施方案和人工智能控制算法和邏輯。物模型、通信協議設計和控制指令交互設計科學、先進,能…

聚類系列(一)——什么是聚類?

目前在做聚類方面的科研工作, 看了很多相關的論文, 也做了一些工作, 于是想出個聚類系列記錄一下, 主要包括聚類的概念和相關定義、現有常用聚類算法、聚類相似性度量指標、聚類評價指標、 聚類的應用場景以及共享一些聚類的開源代碼 下面正式進入該系列的第一個部分&#xff…

webpack打包三方庫直接在html里面使用

場景&#xff1a;我是小程序中使用wxmp-rsa庫進行加密&#xff0c;然后在html里面解密 我就想把wxmp-rsa庫打包到一個js里面&#xff0c;然后在html里面直接引入使用。 webpack配置 const path require("path"); const MiniCssExtractPlugin require("mini-…

【MybatisPlus】簡介與使用

MyBatisPlus 1.簡介 MyBatisPlus&#xff08;簡稱MP&#xff09;是一個MyBatis的增強工具&#xff0c;在MyBatis的基礎上只做增強不做改變&#xff0c;為簡化開發、提高效率而生 官網&#xff1a;https://baomidou.com/ MyBatis-Plus特性&#xff1a; 無侵入&#xff1a;只…

C_1練習題

一、單項選擇題(本大題共20小題,每小題2分,共40分。在每小題給出的四個備選項中,選出一個正確的答案&#xff0c;并將所選項前的字母填寫在答題紙的相應位置上。) 若 x 為int 型變量,則執行以下語句后,x的值為(&#xff09; x5; xx*x; A. 25 B.-20 C. 20 D.-25 若x、i、j、k都…

C#學習相關系列之Linq用法---group和join相關用法(三)

一、Group用法 在C#的LINQ中&#xff0c;Grou將集合中的元素按照指定的鍵進行分組。Group方法返回一個IEnumerable<IGrouping<TKey, TElement>>類型的集合&#xff0c;其中TKey表示分組的鍵類型&#xff0c;TElement表示集合中元素的類型。每個IGrouping<TKey, …

php如何實現文件上傳

php實現文件上傳需要通過全局變量&#xff08;數組&#xff09;&#xff1a;$_FILES 結合 move_uploaded_file 函數來實現。 move_uploaded_file函數&#xff08;只對POST方式生效&#xff09;&#xff1a; 其中move_uploaded_file函數語法&#xff1a;move_uploaded_file(需要…

Vue生成二維碼并進行二維碼圖片下載

1、安包 npm install vue-qr --save2、引入 // vue2.0 import VueQr from vue-qr // vue3.0 import VueQr from vue-qr/src/packages/vue-qr.vue new Vue({components: {VueQr} })<!-- 設備二維碼 對話框 270px--><el-dialog title"點位二維碼" :visible.…

超級簽名封號掉簽該怎么辦

如果超級簽名封號掉簽了&#xff0c;可以考慮以下幾種解決方法&#xff1a; 聯系簽名服務商&#xff1a;首先&#xff0c;可以聯系簽名服務商&#xff0c;了解封號的原因和解決方案。app封裝打包可能會提供技術支持或幫助恢復簽名。 檢查簽名配置&#xff1a;確認簽名配置是否…

練習題——【學習補檔】庫函數的模擬實現

各種庫函數的模擬實現 一、模擬實現strlen1.地址-地址型2.遞歸型3.計數器型 二、模擬實現strcpy三、模擬實現strcmp四、模擬實現strcat五、模擬實現strstr 一、模擬實現strlen 模擬實現strlen有三種方法 1.地址-地址型 2.遞歸型 3.計數器型1.地址-地址型 // //1.地址-地址型 …

云服務器-從零搭建前后端服務

使用須知 選擇0M帶寬不能訪問公網&#xff08;不分配公網IP&#xff09;&#xff0c;如需分配公網IP請增加帶寬值。云服務器ECS默認不開啟虛擬內存如您需要使用請登錄云服務器內部操作。Linux開啟swap&#xff08;虛擬內存&#xff09;、Windows虛擬內存的設置若您購買了數據盤…