设为首页 收藏本站
查看: 1083|回复: 0

[经验分享] ZooKeeper Java Example(官方例子)

[复制链接]

尚未签到

发表于 2019-1-8 08:12:34 | 显示全部楼层 |阅读模式
  为了向您介绍ZooKeeper Java API,我们在这里开发了一个非常简单的观看客户端。该ZooKeeper客户端通过启动或停止程序来观察ZooKeeper节点的更改并进行响应。
要求
有四个要求:
    1.它作为参数:
        ZooKeeper服务的地址
        那么znode的名字就是被观看的
        具有参数的可执行文件
    2.它获取与znode相关联的数据,并启动可执行文件。
    3.如果znode更改,客户端将重新启动内容并重新启动可执行文件。
    4.如果znode消失,客户端将杀死可执行文件。
程序设计
通常,ZooKeeper应用程序分为两个单元,一个维护连接,另一个用于监视数据。在此应用程序中,名为Executor的类维护ZooKeeper连接,并且名为DataMonitor的类监视ZooKeeper树中的数据。
  此外,Executor包含主线程并包含执行逻辑。它负责什么样的用户交互,以及与您作为参数传递的可执行程序的交互以及根据znode的状态关闭和重新启动示例。
  

  1. Executor.java
package com.hellojd.cloud;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* A simple example program to use DataMonitor to start and
* stop executables based on a znode. The program watches the
* specified znode and saves the data that corresponds to the
* znode in the filesystem. It also starts the specified program
* with the specified arguments when the znode exists and kills
* the program if the znode goes away.
*/
public class Executor
        implements Watcher, Runnable, DataMonitor.DataMonitorListener
{
    DataMonitor dm;
    ZooKeeper zk;
    String filename;
    String exec[];
    Process child;
    public Executor(String hostPort, String znode, String filename,
                    String exec[]) throws KeeperException, IOException {
        this.filename = filename;
        this.exec = exec;
        zk = new ZooKeeper(hostPort, 3000, this);
        dm = new DataMonitor(zk, znode, null, this);
    }
    /**
     * @param args
     */
    public static void main(String[] args) {
        if (args.length < 4) {
            System.err
                    .println("USAGE: Executor hostPort znode filename program [args ...]");
            System.exit(2);
        }
        String hostPort = args[0];
        String znode = args[1];
        String filename = args[2];
        String exec[] = new String[args.length - 3];
        System.arraycopy(args, 3, exec, 0, exec.length);
        try {
            new Executor(hostPort, znode, filename, exec).run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /***************************************************************************
     * We do process any events ourselves, we just need to forward them on.
     *
     * @see org.apache.zookeeper.Watcher#process(org.apache.zookeeper.proto.WatcherEvent)
     */
    public void process(WatchedEvent event) {
        System.out.println("Watcher process");
        dm.process(event);
    }
    public void run() {
        try {
            synchronized (this) {
                while (!dm.dead) {
                    wait();
                }
            }
        } catch (InterruptedException e) {
        }
    }
    //以响应ZooKeeper连接永久消失。
    public void closing(int rc) {
        synchronized (this) {
            notifyAll();
        }
    }
    static class StreamWriter extends Thread {
        OutputStream os;
        InputStream is;
        StreamWriter(InputStream is, OutputStream os) {
            this.is = is;
            this.os = os;
            start();
        }
        public void run() {
            byte b[] = new byte[80];
            int rc;
            try {
                while ((rc = is.read(b)) > 0) {
                    os.write(b, 0, rc);
                }
            } catch (IOException e) {
            }
        }
    }
    public void exists(byte[] data) {
        if (data == null) {
            if (child != null) {
                System.out.println("Killing process");
                child.destroy();
                try {
                    child.waitFor();
                } catch (InterruptedException e) {
                }
            }
            child = null;
        } else {
            if (child != null) {
                System.out.println("Stopping child");
                child.destroy();
                try {
                    child.waitFor();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //保存znode数据至文件
            try {
                FileOutputStream fos = new FileOutputStream(filename);
                fos.write(data);
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                System.out.println("Starting child");
                child = Runtime.getRuntime().exec(exec);
                new StreamWriter(child.getInputStream(), System.out);
                new StreamWriter(child.getErrorStream(), System.err);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}  

  2. DataMonitor.java
/**
* A simple class that monitors the data and existence of a ZooKeeper
* node. It uses asynchronous ZooKeeper APIs.
*/
package com.hellojd.cloud;
import java.util.Arrays;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.AsyncCallback.StatCallback;
import org.apache.zookeeper.KeeperException.Code;
import org.apache.zookeeper.data.Stat;
/**
* 另一方面,DataMonitorListener接口不是ZooKeeper API的一部分。 它是一个完全定制的界面,专为此示例应用程序而设计。
* DataMonitor对象使用它来回传给它的容器,它也是Executor对象。
*/
public class DataMonitor implements  StatCallback {
    //Executor或一些类似Executor的对象“拥有”ZooKeeper连接,但可以将事件委托给其他事件到其他对象。
    ZooKeeper zk;
    String znode;
    Watcher chainedWatcher;
    boolean dead;
    //简单地将这些事件转发到DataMonitor来决定如何处理它们
    DataMonitorListener listener;
    byte prevData[];
    // 它主要是异步和事件驱动
    public DataMonitor(ZooKeeper zk, String znode, Watcher chainedWatcher,
                       DataMonitorListener listener) {
        this.zk = zk;
        this.znode = znode;
        this.chainedWatcher = chainedWatcher;
        this.listener = listener;
        // Get things started by checking if the node exists. We are going
        // to be completely event driven
        zk.exists(znode, true, this, null);
    }
    /**
     * 该接口在DataMonitor类中定义,并在Executor类中实现。 当调用Executor.exists()时,执行器根据要求决定是启动还是关闭。
     * 当znode不再存在时,需要说的是杀死可执行文件。
     */
    public interface DataMonitorListener {
        /**
         * The existence status of the node has changed.
         */
        void exists(byte data[]);
        /**
         * The ZooKeeper session is no longer valid.
         *
         * @param rc
         *                the ZooKeeper reason code
         */
        void closing(int rc);
    }
    //响应ZooKeeper状态的更改
    public void process(WatchedEvent event) {
        String path = event.getPath();
        if (event.getType() == Watcher.Event.EventType.None) {
            // We are are being told that the state of the
            // connection has changed
            switch (event.getState()) {
                case SyncConnected:
                    // In this particular example we don't need to do anything
                    // here - watches are automatically re-registered with
                    // server and any watches triggered while the client was
                    // disconnected will be delivered (in order of course)
                    break;
                case Expired:
                    // It's all over
                    dead = true;
                    listener.closing(KeeperException.Code.SessionExpired);
                    break;
            }
        } else {
            if (path != null && path.equals(znode)) {
                // Something has changed on the node, let's find out
                zk.exists(znode, true, this, null);
            }
        }
        if (chainedWatcher != null) {
            chainedWatcher.process(event);
        }
    }
    public void proce***esult(int rc, String path, Object ctx, Stat stat) {
/**
* 首先检查znode存在,致命错误和可恢复错误的错误代码。
* 如果文件(或znode)存在,它将从znode获取数据,然后调用Executor的exists()回调,
* 如果状态已更改。 注意,它不必对getData调用执行异常处理,因为它具有挂起的任何可能导致错误的监视器:
* 如果节点在调用ZooKeeper.getData()之前被删除,则由ZooKeeper设置的监视事件 .exists()触发回调;
*如果发生通信错误,连接回显将触发连接监视事件。
*/
        boolean exists;
        switch (rc) {
            case Code.Ok:
                exists = true;
                break;
            case Code.NoNode:
                exists = false;
                break;
            case Code.SessionExpired:
            case Code.NoAuth:
                dead = true;
                listener.closing(rc);
                return;
            default:
                // Retry errors
                zk.exists(znode, true, this, null);
                return;
        }
        //文件(或znode)存在
        byte b[] = null;
        if (exists) {
            try {
                b = zk.getData(znode, false, null);
            } catch (KeeperException e) {
                // We don't need to worry about recovering now. The watch
                // callbacks will kick off any exception handling
                e.printStackTrace();
            } catch (InterruptedException e) {
                return;
            }
        }
        if ((b == null && b != prevData)
                || (b != null && !Arrays.equals(prevData, b))) {
            listener.exists(b);
            prevData = b;
        }
    }
}  调试:
  参数列表:192.168.0.10:2181 /hellojd_node filename calc
  

  192.168.0.10:2181:ZK地址
  /hellojd_node :监视node
  filename :备份数据文件
  calc:命令
  

  

  来自:http://zookeeper.apache.org/doc/current/javaExample.html




运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-660540-1-1.html 上篇帖子: zookeeper运行优化 下篇帖子: zookeeper 3.4.6 的伪分布式的安装与使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表