在网络环境很是差的状况下,使用zookeeper集群每每会遇到链接expired了:数据库
客户端提示链接从ZOO_CONNECTION_STATE变为ZOO_EXPIRED_SEESION_STATE,而后应用失去与zookeeper集群的链接。服务器
在使用过程当中,咱们通常会加大客户端的rec_timeout值,例如设置为30s,但对是否发生expired没有太大影响,仔细查看文档发现要在服务器端设置minSessionTimeout。网络
那么什么状况下链接会过时?session
当客户端建立链接时,会随机和一个zookeeper节点建立链接,并互发heartbeat;session的信息会同步到其余zookeeper节点上,好比session的id、watcher、临时目录等等信息。并发
当网络抖动或者与他建立链接的zk节点掉线了,这个时候client与zk的的session将断开,此时,client无需处理,zk的重试机制会自动跟其余存活的zk节点建立session:函数
1)若是链接在minSessionTimeout以内链接成功,那么新的链接将同步以前断开链接的临时数据和watcher,并同步状态。性能
2)若是这个重链接过程超过了minSessionTimeout,那么该session就会被zk集群提出去即expired掉,会清除该session全部资源和数据,主要包括临时数据和watcher。当使用zookeeper_init指定session的id去从新链接,也会报错,返回一个空的句柄回来。debug
下面咱们来仔细看看:server
1)通常咱们会设置链接超时时间,在客户端设置,其API为:blog
ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn, int recv_timeout, const clientid_t * clientid, void *context, int flags); 功能: 建立一个句柄(handle)和一个响应(response)这个句柄的会话(session)。 参数: host:zookeeper主机列表,用逗号间隔。 fn:用于监视的回调函数。 clientid:客户端尝试重连的先前会话的ID,若是不须要重连先前的会话,则设置为 0。客户端能够经过调用 zoo_client_id来访问一个已经链接上的而且有效的会话ID,若是clientid对应的会话超时,或者因为某种缘由 clientid变为无效了,那么zookeeper_init 将返回一个非法的 zhandle_t,经过 zhandle_t 的状态能够获知 zookeeper_init 调用失败的缘由。 (一般为 ZOO_EXPIRED_SESSION_STATE). 意思是若是该ID的链接是被expired了的话,从新链接也会失败,服务器已经清理了相关的资源和信息。 context:暂时用不到,忽略。(TODO) flags:设置为0,zookeeper开发团队保留之后使用。
大量,包括代码里面的注释上都没有说recv_timeout的意思,按字面意思,确定不是session_timeout,而是多长时间zk建立链接不成功的时间?
2)在服务器端zoo.conf中有相关设置:minSessionTimeout,最小的客户端超时时间,默认值为2个ticktime,单位是毫秒:
minSessionTimeout 最小的客户端session超时时间,默认值为2个tickTime,单位是毫秒 maxSessionTimeout 最大的客户端session超时时间,默认值为20个tickTime,单位是毫秒
3)因而咱们最终修改的zoo.conf文件为:
tickTime=1000 dataDir=/opt/zookeeper/zkdata dataLogDir=/opt/zookeeper/zklogs clientPort=2181 initLimit=5 syncLimit=2 minSessionTimeout=16000 maxSessionTimeout=30000 server.1=xxxx:2888:3888 server.2=xxxx:2888:3888 server.3=xxxx:2888:3888
注意,在仅配置了minSessionTimeout参数时,zk会启动失败,提示该参数超过了maxSessionTimeout值,这个时候须要在配置文件把最大值也配上。
4)服务端配置详解:
(1)dataDir 用于存放内存数据库快照的文件夹,同时用于集群的myid文件也存在这个文件夹里。 (2)dataLogDir 用于单独设置transaction log的目录,transaction log分离能够避免和普通log还有快照的竞争。 (3)tickTime 心跳时间,为了确保client-server链接存在的,以毫秒为单位,最小超时时间为两个心跳时间。 (4)clientPort 客户端监听端口。 (5)globalOutstandingLimit client请求队列的最大长度,防止内存溢出,默认值为1000。 (6)preAllocSize 预分配的Transaction log空间block为proAllocSize KB,默认block为64M,通常不须要更改,除非snapshot过于频繁。 (7)snapCount 在snapCount个snapshot后写一次transaction log,默认值是100,000。 (8)traceFile 用于记录请求的log,打开会影响性能,用于debug,最好不要定义。 (9)maxClientCnxns 最大并发客户端数,用于防止DOS的,默认值是10,设置为0是不加限制。 (11)clientPortBindAddress 能够设置指定的client ip以及端口,不设置的话等于ANY:clientPort (12)minSessionTimeout 最小的客户端session超时时间,默认值为2个tickTime,单位是毫秒 (13)maxSessionTimeout 最大的客户端session超时时间,默认值为20个tickTime,单位是毫秒 (14)electionAlg 用于选举的实现的参数: ①0:为以原始的基于UDP的方式协做 ②1:为不进行用户验证的基于UDP的快速选举 ③2:为进行用户验证的基于UDP的快速选举 ④3:为基于TCP的快速选举,默认值为3 (15)initLimit 多少个tickTime内,容许其余server链接并初始化数据,若是zooKeeper管理的数据较大,则应相应增大这个值。 (16)syncLimit 多少个tickTime内,容许follower同步,若是follower落后太多,则会被丢弃。 (17)leaderServes leader是否接受客户端链接。默认值为yes。leader负责协调更新。当更新吞吐量远高于读取吞吐量时,能够设置为不接受客户端链接,以便leader能够专一于同步协调工做。 (18)server.x=[hostname]:nnnnn[:nnnnn] 配置集群里面的主机信息,其中: ①server.x:server.x的x要写在myid文件中,决定当前机器的id, ②第一个port用于链接leader, ③第二个用于leader选举。 ④若是electionAlg为0,则不须要第二个port。 ⑤hostname也能够填ip。 (19)group.x=nnnnn[:nnnnn] 分组信息,代表哪一个组有哪些节点,例如group.1=1:2:3 group.2=4:5:6 group.3=7:8:9。 (20)weight.x=nnnnn 权重信息,代表哪一个结点的权重是多少,例如weight.1=1 weight.2=1 weight.3=1。