`
bit1129
  • 浏览: 1070014 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[Zookeeper学习笔记九]Zookeeper源代码分析之Zookeeper构造过程

 
阅读更多

   Zookeeper重载了几个构造函数,其中构造者可以提供参数最多,可定制性最多的构造函数是  

 

public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly)

 

 

    /**
     * To create a ZooKeeper client object, the application needs to pass a
     * connection string containing a comma separated list of host:port pairs,
     * each corresponding to a ZooKeeper server.
     * <p>
     * Session establishment is asynchronous. This constructor will initiate
     * connection to the server and return immediately - potentially (usually)
     * before the session is fully established. The watcher argument specifies
     * the watcher that will be notified of any changes in state. This
     * notification can come at any point before or after the constructor call
     * has returned.
     * <p>
     * The instantiated ZooKeeper client object will pick an arbitrary server
     * from the connectString and attempt to connect to it. If establishment of
     * the connection fails, another server in the connect string will be tried
     * (the order is non-deterministic, as we random shuffle the list), until a
     * connection is established. The client will continue attempts until the
     * session is explicitly closed (or the session is expired by the server).
     * <p>
     * Added in 3.2.0: An optional "chroot" suffix may also be appended to the
     * connection string. This will run the client commands while interpreting
     * all paths relative to this root (similar to the unix chroot command).
     * <p>
     * Use {@link #getSessionId} and {@link #getSessionPasswd} on an established
     * client connection, these values must be passed as sessionId and
     * sessionPasswd respectively if reconnecting. Otherwise, if not
     * reconnecting, use the other constructor which does not require these
     * parameters.
     *
     * @param connectString
     *            comma separated host:port pairs, each corresponding to a zk
     *            server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002"
     *            If the optional chroot suffix is used the example would look
     *            like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a"
     *            where the client would be rooted at "/app/a" and all paths
     *            would be relative to this root - ie getting/setting/etc...
     *            "/foo/bar" would result in operations being run on
     *            "/app/a/foo/bar" (from the server perspective).
     * @param sessionTimeout
     *            session timeout in milliseconds
     * @param watcher
     *            a watcher object which will be notified of state changes, may
     *            also be notified for node events
     * @param sessionId
     *            specific session id to use if reconnecting
     * @param sessionPasswd
     *            password for this session
     * @param canBeReadOnly
     *            (added in 3.4) whether the created client is allowed to go to
     *            read-only mode in case of partitioning. Read-only mode
     *            basically means that if the client can't find any majority
     *            servers but there's partitioned server it could reach, it
     *            connects to one in read-only mode, i.e. read requests are
     *            allowed while write requests are not. It continues seeking for
     *            majority in the background.
     *
     * @throws IOException in cases of network failure
     * @throws IllegalArgumentException if an invalid chroot path is specified
     */
    //sessionId和sessionPasswd用于重连,
    public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            long sessionId, byte[] sessionPasswd, boolean canBeReadOnly)
        throws IOException
    {
        LOG.info("Initiating client connection, connectString=" + connectString
                + " sessionTimeout=" + sessionTimeout
                + " watcher=" + watcher
                + " sessionId=" + Long.toHexString(sessionId)
                + " sessionPasswd="
                + (sessionPasswd == null ? "<null>" : "<hidden>"));
        //设置作为Zookeeper的默认Watcher
        watchManager.defaultWatcher = watcher;
        
        //解析链接串,链接是IP:Port,用逗号分割的串
        ConnectStringParser connectStringParser = new ConnectStringParser(
                connectString);
        
        HostProvider hostProvider = new StaticHostProvider(
                connectStringParser.getServerAddresses());
        //封装IO和Event相关的线程
        cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
                hostProvider, sessionTimeout, this, watchManager,
                getClientCnxnSocket(), sessionId, sessionPasswd, canBeReadOnly);
        cnxn.seenRwServerBefore = true; // since user has provided sessionId
        cnxn.start();
    }

 

 ConnectionStringParser类

  public ConnectStringParser(String connectString) {
        // parse out chroot, if any
        int off = connectString.indexOf('/');
        if (off >= 0) {
            String chrootPath = connectString.substring(off);
            // ignore "/" chroot spec, same as null
            if (chrootPath.length() == 1) {
                this.chrootPath = null;
            } else {
                PathUtils.validatePath(chrootPath);
                this.chrootPath = chrootPath;
            }
            connectString = connectString.substring(0, off);
        } else {
            this.chrootPath = null;
        }

        String hostsList[] = connectString.split(",");
        for (String host : hostsList) {
            int port = DEFAULT_PORT;
            int pidx = host.lastIndexOf(':');
            if (pidx >= 0) {
                // otherwise : is at the end of the string, ignore
                if (pidx < host.length() - 1) {
                    port = Integer.parseInt(host.substring(pidx + 1));
                }
                host = host.substring(0, pidx);
            }
            serverAddresses.add(InetSocketAddress.createUnresolved(host, port));
        }
    }

 ConnectionStringParser类主要是构造函数,构造函数包括两个功能,1.从connectString中解析出chrootPath 2.从connectString解析出Zookeeper服务器列表,解析成InetSocketAddress列表

chrootPath的语法同znode的path一样,以/开头,chrootPath有什么功能呢?

 

HostProvider和StaticHostProvider类

/**
 * A set of hosts a ZooKeeper client should connect to.//Zookeeper客户端尝试建立Zookeeper服务器的服务器列表
 * 
 * Classes implementing this interface must guarantee the following://HostProvider类实现规范
 * 
 * * Every call to next() returns an InetSocketAddress. So the iterator never //next是循环或者随即选取,但是不能返回null
 * ends.
 * 
 * * The size() of a HostProvider may never be zero.//HostProvider的服务器列表不能为空
 * 
 * A HostProvider must return resolved InetSocketAddress instances on next(),
 * but it's up to the HostProvider, when it wants to do the resolving. //HostProvider的next返回resolved InetSocketAddress实例,HostProvider的实现者负责解析InetSocketAddress
 * 
 * Different HostProvider could be imagined: //HostProvider的可能实现
 * 
 * * A HostProvider that loads the list of Hosts from an URL or from DNS //域名或者IP列表
 * * A HostProvider that re-resolves the InetSocketAddress after a timeout. 
 * * A HostProvider that prefers nearby hosts.
 */
public interface HostProvider {
    public int size();

    /**
     * The next host to try to connect to.
     * 
     * For a spinDelay of 0 there should be no wait.
     * 
     * @param spinDelay
     *            Milliseconds to wait if all hosts have been tried once.
     */
    public InetSocketAddress next(long spinDelay);

    /**
     * Notify the HostProvider of a successful connection.
     * 
     * The HostProvider may use this notification to reset it's inner state.
     */
    public void onConnected();
}

 

 StaticHostProivder类的看点是它的构造方法,构造方法实现Resolved Address和Unresolved Address之间的转换,什么是解析了的地址(Resolved Address),什么是未解析的地址(Unresolved Address)呢?

 

/**
     * Constructs a SimpleHostSet.
     * 
     * @param serverAddresses
     *            possibly unresolved ZooKeeper server addresses //传入的参数有可能是没有解析的Zookeeper服务器地址
     * @throws UnknownHostException
     * @throws IllegalArgumentException
     *             if serverAddresses is empty or resolves to an empty list
     */
    public StaticHostProvider(Collection<InetSocketAddress> serverAddresses)
            throws UnknownHostException {
        //对传入的InetSocketAddress进行解析
        for (InetSocketAddress address : serverAddresses) {
            InetAddress ia = address.getAddress();
            InetAddress resolvedAddresses[] = InetAddress.getAllByName((ia!=null) ? ia.getHostAddress():
                address.getHostName());
            for (InetAddress resolvedAddress : resolvedAddresses) {
                // If hostName is null but the address is not, we can tell that
                // the hostName is an literal IP address. Then we can set the host string as the hostname
                // safely to avoid reverse DNS lookup.
                // As far as i know, the only way to check if the hostName is null is use toString().
                // Both the two implementations of InetAddress are final class, so we can trust the return value of
                // the toString() method.
                if (resolvedAddress.toString().startsWith("/") 
                        && resolvedAddress.getAddress() != null) {
                    this.serverAddresses.add(
                            new InetSocketAddress(InetAddress.getByAddress(
                                    address.getHostName(),
                                    resolvedAddress.getAddress()), 
                                    address.getPort()));
                } else {
                    this.serverAddresses.add(new InetSocketAddress(resolvedAddress.getHostAddress(), address.getPort()));
                }  
            }
        }
        
        if (this.serverAddresses.isEmpty()) {
            throw new IllegalArgumentException(
                    "A HostProvider may not be empty!");
        }
        //对服务器列表进行洗牌打乱次序,传说中可以提升可靠性,这里的原因我猜想是在写服务器列表的时候,往往是把按机房一个一个的写,A机房3个Zookeeper,B机房4个Zookeeper,这7个可能是先写完A这里的3个,然后写B的4个
        //打乱次序可以使得A挂了,找到B的可能性大点
        Collections.shuffle(this.serverAddresses);
    }

 

ClientCnxn是客户端跟Zookeeper通信的核心类,单独进行分析

 

 

分享到:
评论

相关推荐

    zookeeper资料

    提供的压缩包文件包括“zookeeper学习笔记.doc”可能包含详细的理论介绍、操作步骤和案例分析;“zookeeper学习笔记.vsdx”可能是一个Visio图表,用于可视化Zookeeper的数据结构、工作流程或架构;而“zookeeper-...

    zookeeper笔记

    4. **源码阅读**:深入理解Zookeeper的工作原理,可以阅读其Java源代码,理解内部实现机制。 通过以上对Zookeeper的介绍,我们可以看到它在分布式系统中扮演着至关重要的角色。无论是作为初学者还是资深开发者,...

    ZooKeeper-:ZooKeeper源码剖析

    优秀时间学习了一下ZooKeeper:分布式过程协调这本书的内容,对ZooKeeper实现的细节很好奇,所以顺便把ZooKeeper源码看了一遍。看完之后想写点内容做个笔记,确实发现不好开始。由于ZooKeeper一个完整的逻辑的代码...

    Hadoop之HBase学习笔记

    【标签】"源码"提示我们,博主可能在笔记中深入到了HBase的源代码层面,分析了HBase的内部工作原理,比如RegionServer如何处理数据分布,HMaster的角色,以及HBase如何通过Zookeeper实现集群管理。"工具"则可能意味...

    《java学习》-SSM实战项目-Java高并发秒杀API,详细流程+学习笔记.zip

    本项目提供了详细的流程说明和学习笔记,帮助开发者更好地掌握相关知识。 首先,`pom.xml`文件是Maven项目的配置文件,它定义了项目依赖,包括SSM框架的各个版本和其他必要的库。通过管理依赖关系,Maven能够自动...

    PyPI 官网下载 | notebuild-1.1.21.tar.gz

    `notebuild`可能是一个用于构建或管理笔记应用的Python库,但具体的用途和功能需要查看其文档或者源代码才能得知。在实际使用前,用户需要先解压此文件,通常可以使用`tar -zxvf notebuild-1.1.21.tar.gz`命令,然后...

    PyPI 官网下载 | cauldron-notebook-1.0.8.tar.gz

    通常,一个Python库的`.tar.gz`格式文件包含了源代码、文档、测试用例和其他资源,便于用户在本地环境中安装和使用。 **Zookeeper 和分布式系统** 提到“zookeeper”,这通常与Apache ZooKeeper有关,这是一个...

    PyPI 官网下载 | dagstermill-0.8.6rc1.tar.gz

    这个压缩包通常包含了源代码、文档和其他必要的文件,以便用户在本地环境中构建和安装该库。 **dagstermill** Dagstermill是与Dagster相关的Python库,Dagster是一个强大的数据工程和机器学习工作流平台。...

    PyPI 官网下载 | mtpdocr-0.1.4.tar.gz

    通过研究其源代码和文档,开发者可以学习到如何构建一个与ZooKeeper集成的云原生Python库,以及如何利用OCR技术解决实际业务问题。无论是对于个人项目还是企业级应用,mtpdocr都可能成为一个强大的工具。

    PyPI 官网下载 | notebook_splitter-1.5.tar.gz

    标题中的"PyPI 官网下载 | notebook_splitter-1.5.tar.gz"指的是Python的包索引(PyPI)上发布的名为`notebook_splitter`的软件包,版本为1.5,其源代码被压缩成tar.gz格式的文件供用户下载。PyPI是Python开发者分享...

    PyPI 官网下载 | wikipedia2vecsm-0.2.1.tar.gz

    通过PyPI下载的压缩包包含了所有必要的源代码和文档,用户可以方便地集成到自己的项目中,利用其进行各种NLP任务的建模和分析。同时,该库的潜力也在于其在云原生环境下的应用,尤其是在分布式计算场景下,能够处理...

    谷粒商城官方笔记.zip

    "资料源码下载地址.txt"可能提供了获取谷粒商城项目源代码的链接,这对于开发者来说是非常宝贵的资源,可以直接参考和学习实际项目中的代码实现。而"软件.zip"和"资料源码.zip"很可能是包含开发所需工具和项目源码的...

    Hadoop深入浅出分享资料

    最后,"如何把hadoop源码关联到eclipse工程中"是针对开发者的内容,说明如何将Hadoop的源代码导入Eclipse这样的集成开发环境,以便于学习、调试或修改Hadoop源码。这通常涉及到克隆Hadoop仓库,配置构建工具如Maven...

    hadoop视频教程珍藏版

    源码解析部分则针对对Hadoop内部机制感兴趣的开发者,深入剖析Hadoop的源代码,帮助理解其设计思想和实现细节。这部分内容可能涉及Hadoop模块的分解,如HDFS的Block、NameNode和DataNode,以及MapReduce的JobTracker...

    大规模分布式系统架构与设计实战笔记8

    "源码"标签表明这篇笔记深入解析了源代码层面的知识,强调了通过阅读和理解开源工具的实现来提升技能的重要性。例如,开发者可能会学习如何利用Hadoop、Spark等大数据处理框架,或者Docker、Kubernetes等容器化和...

    大数据架构技术-吉首大学资料分享.zip

    它提供了笔记本风格的工作环境,便于数据科学家和分析师编写、运行和分享代码,实现快速的数据探索和洞察。 以上知识点构成了大数据处理的基础框架,通过学习和实践,可以有效提升对大数据架构的理解和应用能力。...

    大数据笔记kafka-jvm.zip

    《大数据笔记:深入理解Kafka...通过深入学习《大数据笔记:深入理解Kafka与JVM》,读者将不仅掌握Kafka的基本概念和操作,还能了解到JVM在大数据处理中的关键作用,为在实际工作中应对复杂的大数据挑战打下坚实基础。

    高级java笔试题-itresource:程序开发技术资源集合

    heavyz的Tomcat学习笔记(包括启动流程分析、启动脚本分析) ] () [ java8 新特性讲解系列文章 ] () [ Java 从Jar文件中动态加载类 ] () [ Java并发源码分析 - ThreadPoolExecutor ] () [ java ClassLoader 基本原理 ]...

    hadoop源码归档.zip

    压缩包内的文件主要是法律学习资料,如法考笔记、刑法和民诉的思维导图、讲义等,而不是与Hadoop相关的源代码或IT技术文档。因此,我无法根据这些信息生成关于Hadoop的知识点。 如果您的目标是获取Hadoop的相关知识...

Global site tag (gtag.js) - Google Analytics