使用zk官方包和Curator连接zk集群并测试当服务端挂掉一个端口之后的重连
1、使用zk官方包连接zk集群
1.1、连接服务端的基类代码
public class ClusterBase {
private final static String CLUSTER_CONNECT_STR="192.168.231.131:2181,192.168.231.131:2182,192.168.231.131:2183,192.168.231.131:2184";
private static final int SESSION_TIMEOUT=30 * 1000;
private static ZooKeeper zooKeeper =null;
private static CountDownLatch countDownLatch = new CountDownLatch(1);
private Watcher watcher =new Watcher() {
@Override
public void process(WatchedEvent event) {
if (event.getState() == Event.KeeperState.SyncConnected
&& event.getType()== Event.EventType.None){
countDownLatch.countDown();
System.out.println("连接建立");
}
}
};
@Before
public void init(){
try {
System.out.println(" start to connect to zookeeper server: " + getConnectStr());
zooKeeper=new ZooKeeper(getConnectStr(), getSessionTimeout(), watcher);
System.out.println(" 连接中...");
countDownLatch.await();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static ZooKeeper getZooKeeper() {
return zooKeeper;
}
@After
public void test(){
try {
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected String getConnectStr(){
return CLUSTER_CONNECT_STR;
}
protected int getSessionTimeout() {
return SESSION_TIMEOUT;
}
}
1.2、连接服务操作代码
zk官方包去连接zk集群的话,如果zk集群向外提供的端口挂掉了,我们客户端重连时是需要我们自己捕获异常的,代码如下所示:
@Slf4j
public class ClusterOperations extends ClusterBase {
@Test
public void testReconnect() throws InterruptedException {
while (true){
try {
Stat stat = new Stat();
byte[] data = getZooKeeper().getData("/zookeeper", false, stat);
System.out.println("get data :" + new String(data));
TimeUnit.SECONDS.sleep(5);
}catch (Exception e){
e.printStackTrace();
System.out.println(" 开始重连......");
while (true){
System.out.println("zookeeper status :" + getZooKeeper().getState().name());
if (getZooKeeper().getState().isConnected()) {
break;
}
TimeUnit.SECONDS.sleep(3);
}
}
}
}
1.3、当我们挂掉向外提供的服务时,验证重连
1、首先我们运行操作类,如果出现5s获取一次就是正常
如下图所示:
2、使用 netstat -ntp 命令查看当前集群向外提供的端口,如下图红框中所示:
3、由此可见,集群向外提供的是2183端口,所以当我们停掉2183端口的服务后,观察集群是否能选举成功。
当我们停掉2183端口后,发现控制台重新连接了一下,然后又正常了,如下图所示:
4、如果上述一切正常,我们再次使用 netstat -ntp 命令查看当前集群向外提供的端口,如果集群有向外提供另一个端口,如下图所示,则代表集群在挂掉一个节点之后,选举成功,并使得客户端重新连接。
2、使用Curator连接zk集群
2.1、连接服务端的基类代码
我们也可以使用Curator的代码来测试,其它的步骤都一样,代码如下,
public class CuratorClusterBase {
private final static String CLUSTER_CONNECT_STR="192.168.231.131:2181,192.168.231.131:2182,192.168.231.131:2183,192.168.231.131:2184";
private static final int sessionTimeoutMs = 60*1000;
private static final int connectionTimeoutMs = 5000;
private static CuratorFramework curatorFramework;
@Before
public void init() {
RetryPolicy retryPolicy = new ExponentialBackoffRetry(5000, 30);
curatorFramework = CuratorFrameworkFactory.builder().connectString(getConnectStr())
.retryPolicy(retryPolicy)
.sessionTimeoutMs(sessionTimeoutMs)
.connectionTimeoutMs(connectionTimeoutMs)
.canBeReadOnly(true)
.build();
curatorFramework.getConnectionStateListenable().addListener((client, newState) -> {
if (newState == ConnectionState.CONNECTED) {
System.out.println("连接成功!");
}
});
System.out.println("连接中......");
curatorFramework.start();
}
public void createIfNeed(String path) throws Exception {
Stat stat = curatorFramework.checkExists().forPath(path);
if (stat==null){
String s = curatorFramework.create().forPath(path);
}
}
public static CuratorFramework getCuratorFramework() {
return curatorFramework;
}
@After
public void test(){
try {
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
protected String getConnectStr(){
return CLUSTER_CONNECT_STR;
}
}
2.2、连接服务操作代码
public class CuratorClusterBaseOperations extends CuratorClusterBase {
@Test
public void testCluster() throws Exception {
CuratorFramework curatorFramework = getCuratorFramework();
String pathWithParent = "/zookeeper";
byte[] bytes = curatorFramework.getData().forPath(pathWithParent);
System.out.println(new String(bytes));
while (true) {
try {
byte[] bytes2 = curatorFramework.getData().forPath(pathWithParent);
System.out.println("get data:" + new String(bytes2));
TimeUnit.SECONDS.sleep(5);
} catch (Exception e) {
e.printStackTrace();
testCluster();
}
}
}
}