Zookeeper implements service registration / Discovery (recommended Collection)

Posted by anushka on Tue, 09 Jun 2020 10:05:39 +0200

 

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 time. The effect is as follows:

Effect demonstration

 

1| 0 implementation

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)

				<dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.6.1</version>
        </dependency>

3. Prepare 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
        clientHandler(socket);
    }

    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..");
                    accept.close();
                    break;
                }
                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("10.211.55.4", 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) {
            e.printStackTrace();
            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();
        userClient.run();
        //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 {
                userClient.sendToServer(text);
            }
        }
    }
    
    private void run() throws Exception {
        //Connect zookeeper
        zooKeeper = new ZooKeeper("10.211.55.4:2181", 3000, null);
        //Try to get service information
        getServerInfo();
        //Add permanent listening to service information
        zooKeeper.addWatch(node,this,AddWatchMode.PERSISTENT);
    }

    //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) {
            e.printStackTrace();
        }
    }

    //This method (notification processing) will be executed when the node status sends changes
    @Override
    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");
                getServerInfo();
            } else if (event.getType() == Event.EventType.NodeDataChanged) {
                System.err.println("Service updated");
                getServerInfo();
            }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 {
            socket.connect(server_address);
            //System.out.println("server connection succeeded!");
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write(text.getBytes());
            System.out.println("Message sent successfully!");
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

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:

At the end of the article, if you feel useful, please pay more attention to ha, thank you for reading!

Topics: Zookeeper Java socket Apache