转自:http://crazyjvm.iteye.com/blog/1701032
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也会可能超时,这个等下次再简单结合代码具体谈。