注册不上zookeeper无报错_Zookeeper常见错误笔记

本文详述了Zookeeper开发中遇到的问题,包括zookeeper_init的正确使用、session失效处理、recv_timeout设置误解、zoo_get_children内存泄露及watcher设置等,提供了解决方案和注意事项。
摘要由CSDN通过智能技术生成

Zookeeper开发过程中一些常见问题

一、 关于zookeeper_init函数的使用

问题描述:

开发人员在调用zookeeper_init函数时,若返回一个非空句柄zhandle_t  *zh,则认为初始化成功,这样可能会导致后续操作失败。

问题分析:

zhandle_t  *zookeeper_init(const char *host, watcher_fn fn, int recv_timeout,const   clientid_t *clientid, void *context, int flags) 函 数     返回一个zookeeper客户端与服务器通信的句柄,通常我们仅仅根据返回句柄情况来判断zookeeper 客户端与zookeeper服务器是否 建立连接。如果句柄为空则认为是失败,非空则成功。其实不然,zookeeper_init创建与ZooKeeper服务端通信的句柄以及对应于此句柄的会话,而会话的创建是一个异步的过程,仅当会话建立成功,zookeeper_init才返回一个可用句柄。

问题解决:

如何正确判断zookeepr_init初始化成功,可通过以下三种方式

1、判断句柄的state是否为ZOO_CONNECTED_STATE状态,通过zoo_state(zh)判断状态值是否为ZOO_CONNECTED_STATE。

1

2

3

4

5

6

7

8

9

voidensureConnected()

{

pthread_mutex_lock(&lock);

while(zoo_state(zh)!=ZOO_CONNECTED_STATE)

{

pthread_cond_wait(&cond,&lock);

}

pthread_mutex_unlock(&lock);

}

2、 在zookeeper_init中设置watcher,当zookeeper client与server会话建立后,触发watcher,当 watcher 的state = 3 (ZOO_CONNECTED_STATE), type = -1(ZOO_SESSION_EVENT)时,确认 会话成功建立,此时zookeeper client 初始化成功,可进行后续操作。

3、业务上可以做保证,调用zookeeper_init返回句柄zh,通过该句柄尝试做zoo_exists()或zoo_get_data()等操作,根据操作结果来判断是否初始化成功。

二、 如何解决session失效问题

问题描述:

session失效,导致注册的watcher全部丢失。

问题分析:

如果zookeeper client与server在协商的超时时间内仍没有建立连接,当client与server再次建立连接时,由于session失效了,所有watcher已经被服务器端删除,从而导致所有的watcher需要重新注册。

session 失效,zookeeper client与server重连后所有watcher都会收到两次触发,第一次 wathetr state = 1,type = -1(state = 1表示正在连接中,type = -1 表示session事件);第二次 watcher state = -112,type = -1(state = -112表示session失效)。

问题解决:

可以通过以下两种方法解决session失效问题

1、获取触发session失效watcher后,业务重新注册所有的watcher。

2、不能根本解决,但是可以减小session失效的概率。通过zookeeper client 与server设置更长的session超时时间。(参考下一问题)

三、 为什么zookeeper_init设置recv_timeout较长却没有效果

问题描述:

zookeeper_init设置recv_timeout 100000ms,但客户端与服务端断开连接30s就session失效了。

问题分析:

关于session超时时间的确定:zookeeper_init中设置的超时时间并非真正的session超时时间,session超时时间需要 server与client协商,业务通过zoo_recv_timeout(zhandle_t* zh)获取server与client协商后的超时时间。服务端: minSessionTimeout (默认值为:tickTime * 2) ,  maxSessionTimeout(默认值为:tickTime * 20), ticktime的默认值为2000ms。所以session范围为4s ~ 40s 。客户端:  sessionTimeout, 无默认值,创建实例时设置recv_timeout 值。经常会认为创建zookeeper客户端时设置了sessionTimeout为100s,而没有改变server端的配置,默认值是 不会生效的。 原因: 客户端的zookeeper实例在创建连接时,将sessionTimeout参数发送给了服务端,服务端会根据对应的  minSession/maxSession Timeout的设置,强制修改sessionTimeout参数,也就是修改为4s~40s 返回的参数。所以服务端不一定会以客户端的sessionTImeout做为session expire管理的时间。

问题解决:

增加zookeeper_init recv_timeout大小的同时,需要配置tickTime的值。

tickTime设置是在 conf/zoo.cfg 文件中

# The number of milliseconds of each

ticktickTime=2000  (默认)

注: tickTime 心跳基本时间单位毫秒,ZK基本上所有的时间都是这个时间的整数倍。

四、 zoo_get_children内存泄露问题

问题描述:

调用zoo_get_children函数出现内存泄露问题。

问题分析:

通过查看代码发现问题在于 ZOOAPI int zoo_get_children(zhandle_t *zh, const char *path, int watch,struct String_vector *strings), 该API中String_vector *strings结构体定义如下:

1

2

3

4

5

structString_vector

{

int32_t count;

char**data;

};

Zookeeper API将getchildren结果通过String_vector结构体返回时,malloc分配内存,将子节点所有目录存放在data中,而释放内存需要有客户端来做处理。

问题解决:

调用zoo_get_children(zh, path, watch, strings);需要通过调用zookeper提供的释放内存的方法:deallocate_String_vector(strings)。

1

2

3

4

5

6

7

8

9

10

11

12

13

intdeallocate_String_vector(structString_vector*v){

if(v->data)

{

int32_ti;

for(i=0;icount;i++)

{

deallocate_String(&v->data[i]);

}

free(v->data);

v->data=0;

}

return0;

}

五、 如何正确设置和获取watcher

Watcher 设置是开发中最常见的,需要搞清楚watcher的一些基本特征,对于exists、getdata、getchild对于节点的不同操作会收到不同的 watcher信息。对父节点的变更以及孙节点的变更都不会触发watcher,而对watcher本身节点以及子节点的变更会触发watcher,具体参照下表。

操作

方法

触发watcher

watcher state

watcher type

watcher path

Create当前节点

getdata

×

×

×

×

getchildren

3

4

exists

×

×

×

×

set当前节点

getdata

3

3

getchildren

×

×

×

×

exists

3

3

delete当前节点

getdata

3

2

getchildren

3

2

exists

3

2

create子节点

getdata

×

×

×

×

getchildren

3

4

exists

×

×

×

×

set子节点

getdata

×

×

×

×

getchildren

×

×

×

×

exists

×

×

×

×

delete子节点

getdata

×

×

×

×

getchildren

3

4

exists

×

×

×

×

恢复连接

getdata

1

-1

×

getchildren

1

-1

×

exists

1

-1

×

恢复连接session未超时

getdata

-112

-1

×

getchildren

-112

-1

×

exists

-112

-1

×

恢复连接session超时

getdata

3

-1

×

getchildren

3

-1

×

exists

3

-1

×

注: state = 2 表示删除事件;state = 3表示节点数据变更;state =4表示子节点事件;state = -1表示session事件。 type = -112表示session失效;type = 1表示session建立中;tpye = = 3表示session建立成功。×表示否,√表示是。

六、 zookeeper连接数问题

问题描述:

zookeeper服务器都运行正常,而客户端连接异常。

问题分析:

这是由于zookeeper client连接数已经超过了zookeeper server获取的配置最大连接数。所以导致zookeeper client连接失败。

解决方法:

修改zookeeper安装目录下 conf/zoo.cfg文件。将maxClientCnxns参数改成更大的值。

七、 zookeeper服务器安装相关问题

问题一:是否可以只装一个zookeeper服务器。

问题解答:

可以安装,此时没有leader,follow,此时zookeeper server状态为standalone。

./zkServer.sh status

JMX enabled by default

Using config: /home/bbs/zookeeper-3.4.5/bin/../conf/zoo.cfg

Mode: standalone

关于zoo.cfg配置:

tickTime=2000initLimit=10

syncLimit=5

dataDir=../data

clientPort=4181

问题二:开发没有足够机器,一台机子上是否装三个zookeeper服务器集群。

问题解答:

这种安装模式只能说是一种伪集群模式。三个zookeeper服务器都安装在同一个服务器(platform)上,需保证clientPort不相同。

将zookeeper安装包分别解压在三个目录server1,server2,server3下,配置文件zoo.cfg

Server1配置文件 zoo.cfg,server1在data目录下增加文件myid内容为1。

dataDir=../datadata

LogDir=../dataLog

clientPort=5181

server.1=platform:5888:6888

server.2= platform:5889:6889

server.3= platform:5890:6890

Server2配置文件 zoo.cfg,server1在data目录下增加文件myid内容为2。

dataDir=../datadata

LogDir=../dataLog

clientPort=6181

server.1=platform:5888:6888

server.2= platform:5889:6889

server.3= platform:5890:6890

Server3配置文件 zoo.cfg,server1在data目录下增加文件myid内容为3。

dataDir=../datadata

LogDir=../dataLog

clientPort=7181

server.1=platform:5888:6888

server.2= platform:5889:6889

server.3= platform:5890:6890

启动zookeeper中的常见问题

1.     启动zookeeper后出现noClassFound等等错误,例如:

Exception in thread "main" java.lang.NoSuchMethodError: method java.lang.management.ManagementFactory.getPlatformMBeanServer with signature ()Ljavax.management.MBeanServer; was not found.

at org.apache.zookeeper.jmx.ManagedUtil.registerLog4jMBeans(ManagedUtil.java:48)

at org.apache.zookeeper.server.quorum.QuorumPeerMain.runFromConfig(QuorumPeerMain.java:114)

at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:103)

at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:7

可能原因是该服务器的jdk版本不正确,或是环境变量未设置好。

例如,原来的linux下已经装有jdk-1.4,然后又安装了新版本的jdk-1.6,我们按照网上教程的步骤安装好zookeeper并设置环境变量后,

echo $JAVA_HOME显示java-1.6,

但是用java -version命令发现,仍然显示java-1.4,说明环境变量未配好。zookeeper读取的jdk版本仍然是旧版本的jdk-1.4。

解决方法是在/etc/bashrc文件的末尾,

export JAVA_HOME=/usr/java/jdk1.6.0_23

export JRE_HOME=$JAVA_HOME/jre

export PATH=$JAVA_HOME/bin:$PATH

//这里要注意,应该将$PATH放在尾部而不是放在头部,网上有安装教程写的是$PATH :$JAVA_HOME/bin,这样zookeeper读取的将是$PATH中的jdk旧版本而出错。

export CLASSPATH=.:$JAVA_HOME/lib/*.jar

2. 当一台或某台机器反复出现cannot open channel to xxxx:2888/3888,报错(例如无法与leader进行同步等等错误),无法完成选举(这个错误以前一直有出现,但是时有时无,不知道为什么)。

可能原因是防火墙开启,导致某台机器的端口不能开启,一般是2888不能开启。linux下的很多分布式应用会要求关闭防火墙。。。所以还是干脆关闭算了。今天把防火墙直接关闭后zookeeper启动正常。

用命令service iptables status查看,显示一系列消息,表示防火墙处于开启状态;可以用service iptables stop关闭防火墙。但是这个只是临时关闭防火墙。

要使系统启动时不自动启动防火墙,则可以使用命令chkconfig –list iptables查看防火墙信息,chkconfig iptables off关闭防火墙。以后若要打开,用chkconfig iptables on命令。

3.Zookeeper能够正常启动,但是显示如下错误:

Starting zookeeper…

./zkServer.sh: line 80: /home /sysdata/zookeeper/zookeeper-data/zookeeper_server.pid: No such file or directory

STARTED

在配置文件zoo.cfg文件中指定了zookeeper启动的pid文件的生成位置:dataDir=/home /sysdata/zookeeper/zookeeper-data,但是我们发现该pid并没有生成。而且想要停止zookeeper显然也不能成功:

Stopping zookeeper ...

error: could not find file /zookeeper_server.pid。

zoo.cfg文件中的给dataDir路径赋值前多了一个空格!zookeeper在读取此配置文件时会把空格也读进文件名,将此空格删去后zookeeper启动、关闭就正常了!

原文:http://www.cnblogs.com/binyue/p/4270150.html

在使用Zookeeper时,经常会遇到一些常见错误。其中一种报错是"Starting Zookeeper ...............FAILED TO START",这可能是由于某些原因导致Zookeeper启动失败。为了解决这个问题,可以查看错误日志信息来获取更多的细节。 另外,还有一种常见报错是在单机连接Zookeeper时出现的问题。在Zookeeper 3.5.9版本中,有一个修改,将默认的端口号从2181修改为8080。因此,如果你的服务端口号与8080冲突了,就会出现报错。解决办法是修改服务的端口号,避免与Zookeeper默认端口号冲突。 除了以上两种常见报错,还可能会有其他的报错信息,具体情况需要根据错误日志来判断。我建议你查看具体的错误日志,以获取更准确的故障诊断和解决方案。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Zookeeper异常解决方案](https://blog.csdn.net/weixin_48321993/article/details/125736109)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Zookeeper报错汇总](https://blog.csdn.net/qq_38196524/article/details/119833648)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值