zookeeper node type, integrated code to achieve dynamic server monitoring

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

Guess you like

Origin blog.csdn.net/weixin_52210557/article/details/123437492