启动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.mzph.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;该框架不提供从系统中移除设备的方法。对于由物…

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…

基于SSM的课程资源管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

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

目前在做聚类方面的科研工作, 看了很多相关的论文, 也做了一些工作, 于是想出个聚类系列记录一下, 主要包括聚类的概念和相关定义、现有常用聚类算法、聚类相似性度量指标、聚类评价指标、 聚类的应用场景以及共享一些聚类的开源代码 下面正式进入该系列的第一个部分&#xff…

【MybatisPlus】简介与使用

MyBatisPlus 1.简介 MyBatisPlus&#xff08;简称MP&#xff09;是一个MyBatis的增强工具&#xff0c;在MyBatis的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生 官网&#xff1a;https://baomidou.com/ MyBatis-Plus特性&#xff1a; 无侵入&#xff1a;只…

C#学习相关系列之Linq用法---group和join相关用法(三)

一、Group用法 在C#的LINQ中&#xff0c;Grou将集合中的元素按照指定的键进行分组。Group方法返回一个IEnumerable<IGrouping<TKey, TElement>>类型的集合&#xff0c;其中TKey表示分组的键类型&#xff0c;TElement表示集合中元素的类型。每个IGrouping<TKey, …

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.…

练习题——【学习补档】库函数的模拟实现

各种库函数的模拟实现 一、模拟实现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虚拟内存的设置若您购买了数据盘…

含分布式电源的配电网可靠性评估matlab程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 参考文献&#xff1a; 基于仿射最小路法的含分布式电源配电网可靠性分析——熊小萍 主要内容&#xff1a; 通过概率模型和时序模型分别进行建模&#xff0c;实现基于概率模型最小路法的含分布式电源配电网…

web需求记录

需求1&#xff1a;根据后端传过来的设备名:DESKTOP-4DQRGQB&#xff0c;以及mac:e0:be:03:74:40:0b&#xff1b;iQOO-8&#xff0c;mac:b0:33:66:38:c3:25&#xff0c;用web option 是动态增加的&#xff08;也就是那个选择框里面的东西是根据后端传过来的值动态增加的&#xf…

upload-labs关卡12(基于白名单的%00截断绕过)通关思路

文章目录 前言一、靶场需要了解的前置知识1、%00截断2、0x00截断3、00截断的使用条件1、php版本小于5.3.292、magic_quotes_gpc Off 二、靶场第十二关通关思路1、看源代码2、bp抓包%00截断3、验证文件是否上传成功 总结 前言 此文章只用于学习和反思巩固文件上传漏洞知识&…

LL(1)语法分析程序设计与实现

制作一个简单的C语言词法分析程序_用c语言编写词法分析程序-CSDN博客文章浏览阅读322次。C语言的程序中&#xff0c;有很单词多符号和保留字。一些单词符号还有对应的左线性文法。所以我们需要先做出一个单词字符表&#xff0c;给出对应的识别码&#xff0c;然后跟据对应的表格…

国民新旅游时代,OTA们如何制胜新周期?

文 | 螳螂观察&#xff08;TanglangFin&#xff09; 作者 | 图霖 消费全面复苏的大背景下&#xff0c;旅游业正迎来预期中的拐点。 一个显著表现是&#xff0c;旅游消费正在从可选消费转化成必选消费。 国内消费者旅游需求的不降反增&#xff0c;就是最好的印证。 同程研究…

TypeScript枚举

1、数字枚举 enum Direction {Up,Down,Left,Right, } var Direction; (function (Direction) {Direction[Direction["Up"] 0] "Up";Direction[Direction["Down"] 1] "Down";Direction[Direction["Left"] 2] "L…

[点云分割] 基于颜色的区域增长分割

效果&#xff1a; 代码&#xff1a; #include <iostream> #include <thread> #include <vector>#include <pcl/point_types.h> #include <pcl/io/pcd_io.h> #include <pcl/search/search.h> #include <pcl/search/kdtree.h> #inclu…