`
chenchao051
  • 浏览: 135541 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

ZK Timeout再讨论

阅读更多

http://crazyjvm.iteye.com/blog/1693757 文中提到相关超时问题,但是又出现了一个问题,我把min和max都设置成了180000,但是仍然出现了以下的异常信息:

Client session timed out, have not heard from server in 154339ms for sessionid 0x13a3f7732340003 ...
Client session timed out, have not heard from server in 167805ms for sessionid 0x13a3f7732340000 ...

 

 

我们循着这个异常定位到:ClientCnxn.java

又看到zk存在如下信息:

Established session 0x13a3f773235011b with negotiated timeout 180000 for client /x.x.x.x:49702

这说明我们的配置的确起效果了。那为何还会超时呢,下面几段代码可能会解答这个问题:

异常信息在这里抛出:

if (to <= 0) {
    throw new SessionTimeoutException(
           "Client session timed out, have not heard from server in "
             + idleRecv + "ms"
             + " for sessionid 0x"
             + Long.toHexString(sessionId));
}

 而这段代码在:

 /**
     * This class services the outgoing request queue and generates the heart
     * beats. It also spawns the ReadThread.
     */
class SendThread extends Thread {
   //....
}

 我们可以看到这个类负责维护发信息并且维护心跳,接着往下看这个类中的关键代码,

readTimeout = negotiatedSessionTimeout * 2 / 3;  //我们设置了180s, 那这个值就是120s
connectTimeout = negotiatedSessionTimeout / serverAddrs.size();

 

 long now = System.currentTimeMillis();
        long lastHeard = now;
        long lastSend = now;
        while (zooKeeper.state.isAlive()) {
             try {
                    if (sockKey == null) {
                        // don't re-establish connection if we are closing
                        if (closing) {
                            break;
                        }
                        startConnect();
                        lastSend = now;
                        lastHeard = now;
                    }
                    int idleRecv = (int) (now - lastHeard);
                    int idleSend = (int) (now - lastSend);
                    int to = readTimeout - idleRecv;  //答案就在这行,readTimeout,上面提到120s
                    if (zooKeeper.state != States.CONNECTED) {
                        to = connectTimeout - idleRecv;
                    }
                    if (to <= 0) {
                        throw new SessionTimeoutException(
                                "Client session timed out, have not heard from server in "
                                + idleRecv + "ms"
                                + " for sessionid 0x"
                                + Long.toHexString(sessionId));
                    }
          

假如我没有分析错的话,那么就是这个原因了。

此外lease和rpc也会可能超时,这个等下次再简单结合代码具体谈。

分享到:
评论
2 楼 HowKeyond 2015-01-07  
补充,我代码中监听了session失效事件,并做了重连,但重连要几秒才能连得上,而我们的系统并发频率较大,在重连的过程中有上百个请求找不到这个模块请求失败了,加上这个session失效出现的频率很高,影响很大。
1 楼 HowKeyond 2015-01-07  
请问这一般是什么原因引起的呢?怎么解决?我被这个问题困扰几个星期了,跟踪日志+源代码分析也是找到这里出的异常,但不知是什么原因引起的,它跟zookeeper服务器之间保持的是长连接,给zookeeper发个心跳再读取返回信息理论上应该很快,不可能要几秒甚至上百秒的呀。
期待您的答复,谢谢!

相关推荐

Global site tag (gtag.js) - Google Analytics