Zookeeper implements service registration / discovery

Keywords: Java Zookeeper socket Apache

what that?

Zookeeper is frequently used in distributed development, but many frameworks encapsulate it. Beginners may not understand its working principle well. This article demonstrates the simple demo of using zookeeper to realize service registration and service discovery, hoping to achieve the effect of attracting valuable ideas;

why need RegisterCenter?

The reason why access registration and service discovery are needed is that in the distributed system, services need to call each other, but if each service maintains a copy of dependent service information, it is very troublesome, and the data maintained by itself cannot guarantee its timeliness. When the dependent service information changes, it cannot be updated in time. The solution is to introduce a registration center, The service provider writes its own information to the registration center, and the service user obtains the service information from the registration center, as shown in the following figure:

client represents service user, server represents service provider

Effect: the client can automatically discover the service information. When the service status changes (online, offline, change address), the client can respond to the change in a timely manner. The effect is as follows:

Effect demonstration


  1. First, ensure that Zookeeper can be installed and started, and can be accessed normally

  2. Create Maven project and add the Java client dependency of Zookeeper (note that the version number should be > 3.6)

  3. Write service provider

    package com.jerry;
    import org.apache.zookeeper.CreateMode;
    import org.apache.zookeeper.KeeperException;
    import org.apache.zookeeper.ZooDefs;
    import org.apache.zookeeper.ZooKeeper;
    import org.apache.zookeeper.data.ACL;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.*;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.Enumeration;
    import static java.net.InetAddress.getLocalHost;
    public class UserService {
        public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
            new UserService().serving();
        public void serving() throws IOException, KeeperException, InterruptedException {
            //Get local ip address
            String ip = null;
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface ni = (NetworkInterface) networkInterfaces.nextElement();
                Enumeration<InetAddress> nias = ni.getInetAddresses();
                while (nias.hasMoreElements()) {
                    InetAddress ia = (InetAddress) nias.nextElement();
                    if (!ia.isLinkLocalAddress() && !ia.isLoopbackAddress() && ia instanceof Inet4Address) {
                        ip = ia.getHostAddress();
            int port = 8988;
            //Start service
            ServerSocket socket = new ServerSocket(port);
            System.out.println("Server started...");
            //Registration services
            serverRegister(ip, port);
            //Process request
        private void clientHandler(ServerSocket socket) throws IOException {
            while (true) {
                Socket accept = socket.accept();
                InputStream inputStream = accept.getInputStream();
                byte[] barr = new byte[1024];
                while (true) {
                    int size = inputStream.read(barr);
                    if (size == -1) {
                        //System.out.println("client closed..");
                    String s = new String(barr, 0, size);
                    //Output client message
                    System.out.println(accept.getInetAddress().getHostAddress() + ": " + s);
        private void serverRegister(String ip, int port) throws IOException, KeeperException, InterruptedException {
            //Registration services
            ZooKeeper zooKeeper = new ZooKeeper("", 2181, null);
            try {
                ArrayList<ACL> acl = new ArrayList<>();
                acl.add(new ACL(31, ZooDefs.Ids.ANYONE_ID_UNSAFE));
                zooKeeper.create("/userServer", (ip + ":" + port).getBytes(StandardCharsets.UTF_8), acl, CreateMode.EPHEMERAL);
                System.out.println("Service published successfully!");
            } catch (KeeperException | InterruptedException e) {
                throw e;
  4. Write service user

    package com.yyh;
    import org.apache.zookeeper.*;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.util.Scanner;
    public class UserClient implements Watcher {
        String node = "/userServer"; //The service provider and service consumer of the node where the service information is located are the same
        private ZooKeeper zooKeeper;
        String server_ip;
        int server_port;
        public static void main(String[] args) throws Exception {
            //Start service listening
            UserClient userClient = new UserClient();
            //Interact with services when access is available
            Scanner scanner = new Scanner(System.in);
            while (true){
                System.out.println("Enter information to send(e:sign out)");
                String text = scanner.next();
                if (text.equals("e"))System.exit(-1);
                if (userClient.server_ip == null){
                    System.err.println("No services available...");
                }else {
        private void run() throws Exception {
            //Connect zookeeper
            zooKeeper = new ZooKeeper("", 3000, null);
            //Try to get service information
            //Add permanent listening to service information
        //Get service information
        private void getServerInfo()  {
            try {
                byte[] data = zooKeeper.getData(node, false, null);
                String[] infos = new String(data).split(":");
                server_ip = infos[0];
                server_port = Integer.parseInt(infos[1]);
                System.out.println("Access to service information succeeded!");
                System.out.println(server_ip+":"+ server_port);
            } catch (KeeperException e) {
                System.err.println("Service information does not exist! Waiting for the service to go online........");
            } catch (InterruptedException e) {
        //This method (notification processing) will be executed when the node status sends changes
        public void process(WatchedEvent event) {
            if (event.getPath().equals(node)) {
                //Different event types are handled according to the specific logic. Only the creation, deletion and update of nodes are concerned here
                if (event.getType() == Event.EventType.NodeCreated) {
                    System.err.println("The service is online");
                } else if (event.getType() == Event.EventType.NodeDataChanged) {
                    System.err.println("Service updated");
                }else if (event.getType()== Event.EventType.NodeDeleted){
                    server_ip = null;
                    server_port = 0;
                    System.err.println("The service is offline");
        public void sendToServer(String text) {
            InetSocketAddress server_address = new InetSocketAddress(server_ip, server_port);
            Socket socket = new Socket();
            try {
                //System.out.println("server connection succeeded!");
                OutputStream outputStream = socket.getOutputStream();
                System.out.println("Message sent successfully!");
            } catch (IOException e) {
            try {
            } catch (IOException e) {
  5. Package the server code. This step can be ignored. It is only for testing the correctness of the client. In order to attach all its dependencies when packaging, here add the following content in pom with the help of Spring's packaging plug-in:


    Note: the spring boot packaging plug-in will automatically obtain the main function in the project. It must be ensured that there is only one main function, so it is necessary to temporarily annotate the main function of the client, and finally execute the maven package to get the jar package

  6. Upload jar to virtual machine and run

    java -jar ZookeeperTest-1.0-SNAPSHOT.jar

    If there are no other problems, the client can still connect to the server to send messages;

The above is the specific steps of using Zookeeper to realize service registration and service discovery. In actual development, we may also deploy the services provided as a cluster. At this time, we can register each service information in the cluster as a child node under the specified node. The client listens for the changes of the node, obtains the list of child nodes, and obtains the list of services, On this basis, load balancing algorithm can be added to realize reasonable access to the service list, as shown in the figure:

Posted by phpdev12 on Mon, 08 Jun 2020 21:42:03 -0700