请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

正在回答

16回答

它的源码中是这么说的噢:

https://img1.sycdn.imooc.com//szimg/5ac78ffa0001c18e09120157.jpg

创建会话是异步的,所以你不能里面获取sessionid

你可以灵活使用CountDownLatch,监听watcher,

在sleep的地方 await()

然后如果接受到通知事件类型是会话已经链接,那么就countdown(), 

这样就能获取,这么做要比线程sleep好一点

1 回复 有任何疑惑可以回复我~
  • 提问者 mark_fork #1
    非常感谢!
    回复 有任何疑惑可以回复我~ 2018-04-07 00:16:51
恶汉模式 2018-06-16 23:36:04

我的sessionid也是0,但是我把获取session的代码放到监听里就可以了。好像是异步的。

代码改了

public class ZKConnectSessionWatcher {
 
  final static Logger log = LoggerFactory.getLogger(ZKConnectSessionWatcher.class);

  public static final String zkServerPath = "192.168.1.223:2181";
  public static final Integer timeout = 5000;

  static long sessionId;
  static ZooKeeper zk;
  static ZooKeeper zkSession;

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

     zk = new ZooKeeper(zkServerPath, timeout, new Watcher() {
        @Override
        public void process(WatchedEvent event) {
           log.warn("接受到watch通知:{}", event);
           sessionId = zk.getSessionId();
           String ssid = "0x" + Long.toHexString(sessionId);
           System.out.println(ssid);
           byte[] sessionPassword = zk.getSessionPasswd();
           log.warn("客户端开始连接zookeeper服务器...");
           log.warn("连接状态:{}", zk.getState());
           try {
              new Thread().sleep(1000);
           } catch (InterruptedException e) {
              e.printStackTrace();
           }
           log.warn("连接状态:{}", zk.getState());
           try {
              new Thread().sleep(200);
           } catch (InterruptedException e) {
              e.printStackTrace();
           }

           // 开始会话重连
           log.warn("开始会话重连...");

           try {
              zkSession = new ZooKeeper(zkServerPath,
                    timeout,
                    new Watcher() {
                       @Override
                       public void process(WatchedEvent watchedEvent) {

                          log.warn("重新连接状态zkSession:{}", zkSession.getState());
                          try {
                             new Thread().sleep(1000);
                          } catch (InterruptedException e) {
                             e.printStackTrace();
                          }
                          log.warn("重新连接状态zkSession:{}", zkSession.getState());

                       }
                    },
                    sessionId,
                    sessionPassword);
           } catch (IOException e) {
              e.printStackTrace();
           }

        }
     });

     Thread.sleep(5000);

  }
 
}


1 回复 有任何疑惑可以回复我~
  • 我感觉也是如此,老师的代码中创建完ZooKeeper直接就去获取sessionId了,此时sessionId还没有获取呢,因为它是异步的,连接还没有建立
    回复 有任何疑惑可以回复我~ 2019-06-10 22:49:17
风间影月 2018-04-06 18:49:01

netty 用4.1.12.Final 没有任何问题啊,https://img1.sycdn.imooc.com//szimg/5ac750750001387b00770096.jpg

要不你把你的工程打包上传到百度网盘,链接发出来,我帮你看看

1 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-07 00:32:08

感谢老师,看来还得看源码啊,通常情况下会立即返回给客户端连接产生的sessionId,我也看源码了,无奈没有注释。

https://img1.sycdn.imooc.com//szimg/5ac7a0dc00010e7e17200662.jpg

非常感谢老师!


0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 22:32:10

老师,我调整了获取sessionId sessionPasswd 代码的位置,现在是可以达到session重连的而且sessionId不变的目的了,最主要的问题是,执行了new zkClinet的代码后,sessionId并没有立即分配。这是我系统环境上运行的zk跟老师环境上运行的zk 最大的区别。

我系统配置是 macOS + VirtualBox centOS6.1 仿三台独立物理机的zk集群配置,此外我的zk是早前已经搭建好的,搭建的版本是v3.4.5版本,感觉有个延迟分配SessionId的区别。

更改后代码如下:https://img1.sycdn.imooc.com//szimg/5ac784e10001d8e723481304.jpg

0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 19:54:10

哈哈,我装的centos 虚拟机、我再试试集群环境,感谢老师啦。

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 19:42:13

我穿了我这边的配置,是单机zk的,你试试看

链接:https://pan.baidu.com/s/1741f-kHiNxTJ_ZqhFjOrfw 密码:iufs

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 19:21:52

你试试看集群环境行不行

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 19:17:50

你的工程在我这边没有任何问题啊//img1.sycdn.imooc.com//szimg/5ac750750001387b00770096.jpg

你的环境是啥,linux啊什么的

0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 18:55:39

老师,上传代码了,谢谢:

https://pan.baidu.com/s/1UQg9yllaNiu2WlzvwbquxA

0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 18:29:32

老师,如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.imooc</groupId>
   <artifactId>imooc-zookeeper-starter</artifactId>
   <version>0.0.1-SNAPSHOT</version>

   <dependencies>

       <dependency>
           <groupId>org.apache.zookeeper</groupId>
           <artifactId>zookeeper</artifactId>
           <version>3.4.11</version>
       </dependency>

       <!-- 日志处理 -->
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.7.21</version>
       </dependency>
       <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-log4j12</artifactId>
           <version>1.7.21</version>
       </dependency>

       <!--<dependency>-->
           <!--<groupId>io.netty</groupId>-->
           <!--<artifactId>netty-all</artifactId>-->
           <!--<version>4.1.12.Final</version>-->
       <!--</dependency>-->
       <dependency>
           <groupId>io.netty</groupId>
           <artifactId>netty</artifactId>
           <version>3.10.5.Final</version>
       </dependency>

       <dependency>
           <groupId>log4j</groupId>
           <artifactId>log4j</artifactId>
           <version>1.2.16</version>
       </dependency>

       <dependency>
           <groupId>org.apache.servicemix.bundles</groupId>
           <artifactId>org.apache.servicemix.bundles.jline</artifactId>
           <version>0.9.94_1</version>
       </dependency>

       <dependency>
           <groupId>org.apache.yetus</groupId>
           <artifactId>audience-annotations</artifactId>
           <version>0.5.0</version>
       </dependency>

   </dependencies>
</project>

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 18:25:18

你把你的pom.xml文件发我一下吧,我来试试

0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 17:51:27

老师,更改之后代码,初次连接之后,sessionId拿到的值是0,我采用的是编辑器是idea,在Zookeeper zk = new Zookeeper上打了个断点,单步调试的,同时设立了三台独立的虚拟机,虚拟机也在宿主机上配置了host ip  映射。

程序更改之后,debug信息如下:

//img1.sycdn.imooc.com//szimg/5ac7430a000131c122781378.jpg

jar包采用 maven引入,唯一不同的是,我引入的netty包是 4.1.12,而老师源代码中引入的jar包是3.10.5。

会不会是网络传输这一层的NIO出了问题?我引入的jar包版本太高?

https://img1.sycdn.imooc.com//szimg/5ac744140001a62c08600336.jpg

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 17:33:24

"eshop-cache01:2181"  连接zk的时候,这个服务地址,我改为了IP,没有任何问题,sessionId也是一致的,你这边改一下吧,改成你自己的再试试:{ip}:{port}

0 回复 有任何疑惑可以回复我~
提问者 mark_fork 2018-04-06 17:02:51

谢谢老师,这个代码是session重连那一节的代码:

package com.imooc.zk.demo;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* @Title: ZKConnectDemo.java
* @Description: zookeeper 恢复之前的会话连接demo演示
*/
public class ZKConnectSessionWatcher implements Watcher {
 
  final static Logger log = LoggerFactory.getLogger(ZKConnectSessionWatcher.class);

  public static final String zkServerPath = "eshop-cache01:2181";
  public static final Integer timeout = 10000;
 
  public static void main(String[] args) throws Exception {
     
     ZooKeeper zk = new ZooKeeper(zkServerPath, timeout, new ZKConnectSessionWatcher());

     long sessionId = zk.getSessionId();
     String ssid = "0x" + Long.toHexString(sessionId);
     System.out.println(ssid);
     byte[] sessionPassword = zk.getSessionPasswd();
     //放到session 或者 redis当中
     
     log.warn("客户端开始连接zookeeper服务器...");
     log.warn("连接状态:{}", zk.getState());
     new Thread().sleep(1000);
     log.warn("连接状态:{}", zk.getState());
     
     new Thread().sleep(200);

     // 开始会话重连
     log.warn("开始会话重连...");
     
     ZooKeeper zkSession = new ZooKeeper(zkServerPath,
                                timeout,
                                new ZKConnectSessionWatcher(),
                                sessionId,
                                sessionPassword);
     log.warn("重新连接状态zkSession:{}", zkSession.getState());
     new Thread().sleep(1000);
     log.warn("重新连接状态zkSession:{}", zkSession.getState());
  }

  public void process(WatchedEvent event) {
     log.warn("接受到watch通知:{}", event);
  }
}

0 回复 有任何疑惑可以回复我~
风间影月 2018-04-06 16:16:41

第一个zk的状态已经关闭了,那么第二个再去连的话,会生成新的会话。代码这么看没啥问题,要不复制出来我帮你试试

0 回复 有任何疑惑可以回复我~
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信