[ 
https://issues.apache.org/jira/browse/ZOOKEEPER-2615?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15574296#comment-15574296
 ] 

guoping.gp edited comment on ZOOKEEPER-2615 at 10/14/16 5:41 AM:
-----------------------------------------------------------------

REPRODUCE TEST CASE STEP BY STEP
====================================
1).  start zookeeper cluster, says server1(localhost:6181), 
server2(localhost:4181), server3(localhost:2181)
    let's assume now server2 is the LEADER.

2). use zkCli.sh create a persistence node /curator_exists_watch

3). use Curator Framework2.9.1 to create a simple Java Client Application,  as 
following:

*****

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.WatchedEvent;

public class ExistingWatchDemo {

        public static void main(String[] args) throws Exception {

                CuratorFrameworkFactory.Builder builder = 
CuratorFrameworkFactory.builder();
                builder = builder.connectString("localhost:2181,localhost:6181")
                                         .sessionTimeoutMs(15000)
                                         .connectionTimeoutMs(10000)
                                        .retryPolicy(new 
ExponentialBackoffRetry(5000, Integer.MAX_VALUE));
                
                final CuratorFramework zkClient = builder.build();

                zkClient.start();

                CuratorWatcher watcher = new CuratorWatcher() {

                        public void process(WatchedEvent event) throws 
Exception {
                                 System.out.println("received event " + event);
                                 System.out.println("watch again ...");
                                
zkClient.checkExists().usingWatcher(this).forPath("/curator_exists_watch");
                        }
                        
                };
                
                
zkClient.checkExists().usingWatcher(watcher).forPath("/curator_exists_watch");

                Thread.sleep(600 * 1000);

        }

}

*****

to stay us to reproduce in more convenience, here we provide only 2 servers in 
the connection string instead of 3 both, says as server1(FOLLOWING) 
server3(FOLLOWING)

4).  breakpoint at 2 places: 
 
    FinalRequestProcessor.java: line 303 :         
zks.getZKDatabase().setWatches(relativeZxid, 
    NIOServerCnxn.java: line 966:                     
synchronized(factory.cnxns){


5).  running the client app ExistingWatchDemo.java, let say the client 
application connection to server3(2181)

6). use the IDE make a remote debug session connect to another server of the 
connection string which we provided, here server1(6181)

7). now kill -STOP server3(2181), the client app will find the server hang and 
reconnect to  server1(6181), we can confirm the reconnect in
the client's log:

---------
016-10-14 13:31:21,505 [myid:] - INFO  
[main-SendThread(localhost:2181):ClientCnxn$SendThread@1096] - Client session 
timed out, have not heard from server in 3754ms for sessionid 
0x357c1a4462b000e, closing socket connection and attempting reconnect
2016-10-14 13:31:22,389 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@975] - Opening socket 
connection to server localhost/0:0:0:0:0:0:0:1:6181. Will not attempt to 
authenticate using SASL (unknown error)
2016-10-14 13:31:22,392 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@852] - Socket connection 
established to localhost/0:0:0:0:0:0:0:1:6181, initiating session
2016-10-14 13:31:22,392 [myid:] - DEBUG 
[main-SendThread(localhost:6181):ClientCnxn$SendThread@892] - Session 
establishment request sent on localhost/0:0:0:0:0:0:0:1:6181
2016-10-14 13:31:22,407 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@1235] - Session 
establishment complete on server localhost/0:0:0:0:0:0:0:1:6181, sessionid = 
0x357c1a4462b000e, negotiated timeout = 15000
---------

the reconnect will hit the breakpoint FinalRequestProcessor.java: line 303 as 
following:

Thread [CommitProcessor:1] (Suspended (breakpoint at line 303 in 
FinalRequestProcessor))        
        FinalRequestProcessor.processRequest(Request) line: 303 
        CommitProcessor.run() line: 74  

8). now kill the process of  the client app, kill -9 <pid of client app>, this 
will let us another breakpoint hit, as following
 
Daemon Thread [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:6181] (Suspended 
(breakpoint at line 966 in NIOServerCnxn)) 
        NIOServerCnxn.close() line: 966 
        NIOServerCnxn.doIO(SelectionKey) line: 360      
        NIOServerCnxnFactory.run() line: 208    
        Thread.run() line: 745  

9).  now resume the breakpoint(NIOServerCnxn:966) in step 8, after that, then 
resume the breakpoint (FinalRequestProcessor:303) in step 7

10). now use wchp and cons to check the leak watch, as following shows

pguodeMacBook-Air:bin pguo$ echo wchp | nc localhost 6181
/curator_exists_watch
        0x357c1a4462b000e

pguodeMacBook-Air:bin pguo$ echo cons | nc localhost 6181
 /0:0:0:0:0:0:0:1:61702[0](queued=0,recved=1,sent=0)
 


was (Author: guoping.gp):
REPRODUCE TEST CASE STEP BY STEP
====================================
1. start zookeeper cluster, says server1(localhost:6181), 
server2(localhost:4181), server3(localhost:2181)
    let's assume now server2 is the LEADER.

2. use zkCli.sh create a persistence node /curator_exists_watch

3. use Curator Framework2.9.1 to create a simple Java Client Application,  as 
following:

*****

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.api.CuratorWatcher;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.WatchedEvent;

public class ExistingWatchDemo {

        public static void main(String[] args) throws Exception {

                CuratorFrameworkFactory.Builder builder = 
CuratorFrameworkFactory.builder();
                builder = builder.connectString("localhost:2181,localhost:6181")
                                         .sessionTimeoutMs(15000)
                                         .connectionTimeoutMs(10000)
                                        .retryPolicy(new 
ExponentialBackoffRetry(5000, Integer.MAX_VALUE));
                
                final CuratorFramework zkClient = builder.build();

                zkClient.start();

                CuratorWatcher watcher = new CuratorWatcher() {

                        public void process(WatchedEvent event) throws 
Exception {
                                 System.out.println("received event " + event);
                                 System.out.println("watch again ...");
                                
zkClient.checkExists().usingWatcher(this).forPath("/curator_exists_watch");
                        }
                        
                };
                
                
zkClient.checkExists().usingWatcher(watcher).forPath("/curator_exists_watch");

                Thread.sleep(600 * 1000);

        }

}

*****

to stay us to reproduce in more convenience, here we provide only 2 servers in 
the connection string instead of 3 both, says as server1(FOLLOWING) 
server3(FOLLOWING)

4.  breakpoint at 2 places: 
 
    FinalRequestProcessor.java: line 303 :         
zks.getZKDatabase().setWatches(relativeZxid, 
    NIOServerCnxn.java: line 966:                     
synchronized(factory.cnxns){


5. running the client app ExistingWatchDemo.java, let say the client 
application connection to server3(2181)

6. use the IDE make a remote debug session connect to another server of the 
connection string which we provided, here server1(6181)

7. now kill -STOP server3(2181), the client app will find the server hang and 
reconnect to  server1(6181), we can confirm the reconnect in
the client's log:

---------
016-10-14 13:31:21,505 [myid:] - INFO  
[main-SendThread(localhost:2181):ClientCnxn$SendThread@1096] - Client session 
timed out, have not heard from server in 3754ms for sessionid 
0x357c1a4462b000e, closing socket connection and attempting reconnect
2016-10-14 13:31:22,389 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@975] - Opening socket 
connection to server localhost/0:0:0:0:0:0:0:1:6181. Will not attempt to 
authenticate using SASL (unknown error)
2016-10-14 13:31:22,392 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@852] - Socket connection 
established to localhost/0:0:0:0:0:0:0:1:6181, initiating session
2016-10-14 13:31:22,392 [myid:] - DEBUG 
[main-SendThread(localhost:6181):ClientCnxn$SendThread@892] - Session 
establishment request sent on localhost/0:0:0:0:0:0:0:1:6181
2016-10-14 13:31:22,407 [myid:] - INFO  
[main-SendThread(localhost:6181):ClientCnxn$SendThread@1235] - Session 
establishment complete on server localhost/0:0:0:0:0:0:0:1:6181, sessionid = 
0x357c1a4462b000e, negotiated timeout = 15000
---------

the reconnect will hit the breakpoint FinalRequestProcessor.java: line 303 as 
following:

Thread [CommitProcessor:1] (Suspended (breakpoint at line 303 in 
FinalRequestProcessor))        
        FinalRequestProcessor.processRequest(Request) line: 303 
        CommitProcessor.run() line: 74  

8. now kill the process of  the client app, kill -9 <pid of client app>, this 
will let us another breakpoint hit, as following
 
Daemon Thread [NIOServerCxn.Factory:0.0.0.0/0.0.0.0:6181] (Suspended 
(breakpoint at line 966 in NIOServerCnxn)) 
        NIOServerCnxn.close() line: 966 
        NIOServerCnxn.doIO(SelectionKey) line: 360      
        NIOServerCnxnFactory.run() line: 208    
        Thread.run() line: 745  

9.  now resume the breakpoint(NIOServerCnxn:966) in step 8, after that, then 
resume the breakpoint (FinalRequestProcessor:303) in step 7

10. now use wchp and cons to check the leak watch, as following shows

pguodeMacBook-Air:bin pguo$ echo wchp | nc localhost 6181
/curator_exists_watch
        0x357c1a4462b000e

pguodeMacBook-Air:bin pguo$ echo cons | nc localhost 6181
 /0:0:0:0:0:0:0:1:61702[0](queued=0,recved=1,sent=0)
 

> Zookeeper server holds onto dead/expired session ids in the watch data 
> structures
> ---------------------------------------------------------------------------------
>
>                 Key: ZOOKEEPER-2615
>                 URL: https://issues.apache.org/jira/browse/ZOOKEEPER-2615
>             Project: ZooKeeper
>          Issue Type: Bug
>          Components: server
>    Affects Versions: 3.4.6
>            Reporter: guoping.gp
>
> The same issue (https://issues.apache.org/jira/browse/ZOOKEEPER-1382) still 
> can be found even with zookeeper 3.4.6.
> this issue cause our production zookeeper cluster leak about 1 million 
> watchs, after restart the server one by one, the watch count decrease to only 
> about 40000.
> I can reproduce the issue on my mac,here it is:
> ------------------------------------------------------------------------
> pguodeMacBook-Air:bin pguo$ echo srvr | nc localhost 6181
> Zookeeper version: 3.4.6-1569965, built on 02/20/2014 09:09 GMT
> Latency min/avg/max: 0/1156/128513
> Received: 539
> Sent: 531
> Connections: 1
> Outstanding: 0
> Zxid: 0x100000037
> Mode: follower
> Node count: 5
> ------------------------
> pguodeMacBook-Air:bin pguo$ echo cons | nc localhost 6181
>  
> /127.0.0.1:55759[1](queued=0,recved=5,sent=5,sid=0x157be2732d0000e,lop=PING,est=1476372631116,to=15000,lcxid=0x1,lzxid=0xffffffffffffffff,lresp=1476372646260,llat=8,minlat=0,avglat=6,maxlat=17)
>  /0:0:0:0:0:0:0:1:55767[0](queued=0,recved=1,sent=0)
> ------------------------
> pguodeMacBook-Air:bin pguo$ echo wchp | nc localhost 6181
> /curator_exists_watch
>               0x357be48e4d90007
>               0x357be48e4d90009
>               0x157be2732d0000e
> as above 4-letter's report shows,     0x357be48e4d90007 and 0x357be48e4d90009 
> are leaked after the two sessions expired 



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to