Node type
Persistent: After the client and server are disconnected, the created node is not deleted
It can be divided into unsequential number and sequential number. The sequence number can be used to globally sort all events, so that the client can infer the order of events through the sequence number.
Ephemeral: After the client and server are disconnected, the created node deletes itself
It can also be divided into unsequential and sequential
Create Node in Linux
Create a permanent node with name jiedian1, value dadada, no serial number
create /jiedian1 "dadada"
Create child nodes
create /jiedian1/zijiedian "dadada"
get node value
get -s /jiedian1
To create a node with a serial number, just add -s
create -s /jiedian1/zijiedian "xuhao"
create temporary
create -e /jiedian2 "linshi"
Temporary serial number
create -e -s /jiedian2 "linshixuhao"
At this point, after quit exits, the temporary node will disappear
modify node
set /jiedian1 "123"
Listener Principle
Listen for changes in that node's data, and notify the client if there is a change
1) First, there must be a main() thread
2) Create the Zookeeper client in the main thread, then two threads will be created, one responsible for network connection communication (connet) and one responsible for listening (listener).
3) Send the registered listening events to Zookeeper through the connect thread.
4) Add the registered listener events to the list in Zookeeper's list of registered listeners.
5) Zookeeper will send this message to the listener thread when it detects that there is a data or path change.
6) The process() method is called inside the listener thread.
Using the command line operation, register once and listen once
get -w / jiedian1
At this time, other machines are used to modify the node, and the current client will be notified at this time.
integration code
Create a maven project and add dependencies
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.5.7</version>
</dependency>
</dependencies>
Configure the log file and create log4j.properties under resource
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
write test class
public class zkClient {
//不能有空格
private static String connectString = "192.168.6.100:2181,192.168.6.101:2181,192.168.6.102:2181";
//超时时间
private static int sessionTimeout = 2000;
private ZooKeeper zkClient = null;
//接连集群
@Before
public void init() throws Exception {
zkClient = new ZooKeeper(connectString, sessionTimeout, new
Watcher() {
@Override
public void process(WatchedEvent watchedEvent) {
// 收到事件通知后的回调函数(用户的业务逻辑)
System.out.println(watchedEvent.getType() + "--"
+ watchedEvent.getPath());
// 再次启动监听
try {
List<String> children = zkClient.getChildren("/",
true);
for (String child : children) {
System.out.println(child);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// 创建子节点
@Test
public void create() throws Exception {
// 参数 1:要创建的节点的路径; 参数 2:节点数据 ; 参数 3:节点权限 ;参数 4:节点的类型
String nodeCreated = zkClient.create("/lzq",
"jiedain".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
CreateMode.PERSISTENT);
}
// 获取子节点并监听 注册一次生效一次
@Test
public void getChildren() throws Exception {
List<String> children = zkClient.getChildren("/", true);
for (String child : children) {
System.out.println(child);
}
// 延时阻塞
Thread.sleep(Long.MAX_VALUE);
}
}
write data flow
The write request of the write process is directly sent to the leader node, written directly, and then synchronized to the slave node. When more than half of the write is completed, it is returned to the client
The write request of the write process is sent to the follower node to notify the master node to write. . . .
Server dynamic online and offline monitoring
In a distributed system, there can be multiple master nodes, which can go online and offline dynamically, and any client can sense the master node server's online and offline in real time.
First create the /servers node on the cluster
create /servers "servers"
In IDEA, the server registers the code with Zookeeper
import java.io.IOException;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.ZooDefs.Ids;
public class DistributeServer {
private static String connectString =
"192.168.6.100:2181,192.168.6.101:2181,192.168.6.102:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";
// 创建到 zk 的客户端连接
public void getConnect() throws IOException{
zk = new ZooKeeper(connectString, sessionTimeout, new
Watcher() {
@Override
public void process(WatchedEvent event) {
}
});
}
// 注册服务器
public void registServer(String hostname) throws Exception{
String create = zk.create(parentNode + "/server",
hostname.getBytes(), Ids.OPEN_ACL_UNSAFE,
CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(hostname +" is online "+ create);
}
// 业务功能
public void business(String hostname) throws Exception{
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]);
}
}
client
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
public class DistributeClient {
private static String connectString =
"192.168.6.100:2181,192.168.6.101:2181,192.168.6.102:2181";
private static int sessionTimeout = 2000;
private ZooKeeper zk = null;
private String parentNode = "/servers";
// 创建到 zk 的客户端连接
public void getConnect() throws IOException {
zk = new ZooKeeper(connectString, sessionTimeout, new
Watcher() {
@Override
public void process(WatchedEvent event) {
// 再次启动监听
try {
getServerList();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
// 获取服务器列表信息
public void getServerList() throws Exception {
// 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);
}
// 业务功能
public void business() throws Exception{
System.out.println("client is working ...");
Thread.sleep(Long.MAX_VALUE);
}
public static void main(String[] args) throws Exception {
// 1 获取 zk 连接
DistributeClient client = new DistributeClient();
client.getConnect();
// 2 获取 servers 的子节点信息,从中获取服务器信息列表
client.getServerList();
// 3 业务进程启动
client.business();
}
}
At this point, modifying or creating a node will output in the console