ZooKeeper之服务器动态上下线案例

2022-10-14,,,,

需求

某分布式系统中,主节点可以有多台,可以动态下线,任意一台客户端都能实时感知到主节点服务器的上下线。

需求分析

 

 

具体实现

先在集群上创建/servers节点

create /servers "servers"

一些依赖

pom.xml:

<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.mcq</groupid>
  <artifactid>zookeeper1026</artifactid>
  <version>0.0.1-snapshot</version>
  <dependencies>
		<dependency>
			<groupid>junit</groupid>
			<artifactid>junit</artifactid>
			<version>release</version>
		</dependency>
		<dependency>
			<groupid>org.apache.logging.log4j</groupid>
			<artifactid>log4j-core</artifactid>
			<version>2.8.2</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.zookeeper/zookeeper -->
		<dependency>
			<groupid>org.apache.zookeeper</groupid>
			<artifactid>zookeeper</artifactid>
			<version>3.4.10</version>
		</dependency>
</dependencies>
</project>

 在src/main/resources下添加一个file log4j.properties:

log4j.rootlogger=info, stdout  
log4j.appender.stdout=org.apache.log4j.consoleappender  
log4j.appender.stdout.layout=org.apache.log4j.patternlayout  
log4j.appender.stdout.layout.conversionpattern=%d %p [%c] - %m%n  
log4j.appender.logfile=org.apache.log4j.fileappender  
log4j.appender.logfile.file=target/spring.log  
log4j.appender.logfile.layout=org.apache.log4j.patternlayout  
log4j.appender.logfile.layout.conversionpattern=%d %p [%c] - %m%n

 

服务器端向 zookeeper 注册代码

package com.mcq.zookeeper1026;

import java.io.ioexception;

import org.apache.zookeeper.createmode;
import org.apache.zookeeper.keeperexception;
import org.apache.zookeeper.watchedevent;
import org.apache.zookeeper.watcher;
import org.apache.zookeeper.zoodefs.ids;
import org.apache.zookeeper.zookeeper;

public class distributeserver {
	private string connectstring = "hadoop103:2181,hadoop104:2181,hadoop105:2181";
	private int sessiontimeout = 2000;
	private zookeeper zk = null;
	private string parentnode = "/servers";

	public void getconnect() throws ioexception {
		zk = new zookeeper(connectstring, sessiontimeout, new watcher() {

			@override
			public void process(watchedevent event) {
				// todo auto-generated method stub

			}

		});
	}

	// 注册服务器
	public void registserver(string hostname) throws exception {
		system.out.println(zk);
		string path = zk.create(parentnode + "/server", hostname.getbytes(), ids.open_acl_unsafe,
				createmode.ephemeral_sequential);
		system.out.println(hostname + " is online " + path);
	}

	// 业务功能
	public void business(string hostname) throws interruptedexception {
		system.out.println(hostname + " is working ……");
		thread.sleep(long.max_value);
	}

	public static void main(string[] args) throws exception {
		// 1.获取zk连接
		distributeserver server = new distributeserver();
		server.getconnect();
		// 2.利用zk连接注册服务器信息
		server.registserver(args[0]);
		// 3.启动业务功能
		server.business(args[0]);

	}
}

 

客户端代码

package com.mcq.zookeeper1026;

import java.io.ioexception;
import java.util.arraylist;
import java.util.list;

import org.apache.zookeeper.keeperexception;
import org.apache.zookeeper.watchedevent;
import org.apache.zookeeper.watcher;
import org.apache.zookeeper.zookeeper;

public class distributeclient {
	public static void main(string[] args) throws ioexception, keeperexception, interruptedexception {
		//1.获取zk连接
		distributeclient client=new distributeclient();
		client.getconnect();
		//2.获取servers的子节点信息,从中获取服务器信息列表
		client.getserverlist();
		//3.业务进程启动
		client.business();
	}

	private void business() throws interruptedexception {
		// todo auto-generated method stub
		system.out.println("client is working ……");
		thread.sleep(long.max_value);
	}

	private string parentnode="/servers";

	private void getserverlist() throws keeperexception, interruptedexception {
		// todo auto-generated method stub
		//1.获取服务器子节点信息,并且对父节点进行监听
		list<string> children = zk.getchildren(parentnode,true);
		//2.存储服务器信息列表
		arraylist<string> servers=new arraylist<>();
		//3.遍历所有节点,获取节点中的主机名称信息
		for(string child:children) {
			byte[] data=zk.getdata(parentnode+"/"+child,false,null);
			servers.add(new string(data));
		}
		//4.打印服务器列表信息
		system.out.println(servers);
	}

	private zookeeper zk=null;
	private string connectstring="hadoop103:2181,hadoop104:2181,hadoop105:2181";
	private int sessiontimeout=2000;

	private void getconnect() throws ioexception {
		// todo auto-generated method stub
		//创建到zk的客户端连接
		zk=new zookeeper(connectstring,sessiontimeout,new watcher() {

			@override
			public void process(watchedevent event) {
				// todo auto-generated method stub
				try {
					getserverlist();
				}catch(exception e) {
					e.printstacktrace();
				}
			}
			
		});
	}
}

 

运行程序

先运行客户端

在xshell上登录客户端(bin/zkcli.sh),进行一些操作,可以看到eclipse的控制台会实时输出有哪些节点。

 

然后运行服务器端,记得先在run configuration里设置一下参数,比如设成hadoop103,那么运行后,客户端的控制台会实时显示当前的节点。

 

 点上面那个红框可以切换控制台。

 

《ZooKeeper之服务器动态上下线案例.doc》

下载本文的Word格式文档,以方便收藏与打印。