zookeeper代码阅读-主要代码逻辑

来源:互联网 发布:淘宝怎么发布虚拟宝贝 编辑:程序博客网 时间:2024/06/08 11:50

zookeeper集群有两种工作状态,一种是恢复状态(选leader状态),一种是广播状态(正常工作状态)。好比公司的管理一样,高层开会后决定职责任务,然后各部门负责人专职专管。

以下代码的循环体就是集群工作的循环状态。可以看到每个机器都会保存自己现在的状态,enum类型参数,总共有四种状态LOOKING, FOLLOWING, LEADING, OBSERVING。这四种状态也就对应四种角色,之前也介绍了机器角色的功能,这里不多说。

以下代码来自QuarumPeer.class 和 FastLeadElection。QuarumPeer是集群启动状态的核心代码。这里先介绍比较核心的 部分。 以下代码是机器工作时候的主循环代码,可以看到在机器保存running的时候,他会不停的根据自己的状态去做该状态应该做的事情。FastLeadElection是当机器处于looking状态时候要做的事情,会同步leader或者和其它机器共同选取leader。

        updateThreadName();        LOG.debug("Starting quorum peer");        try {            jmxQuorumBean = new QuorumBean(this);            MBeanRegistry.getInstance().register(jmxQuorumBean, null);            for(QuorumServer s: getView().values()){                ZKMBeanInfo p;                if (getId() == s.id) {                    p = jmxLocalPeerBean = new LocalPeerBean(this);                    try {                        MBeanRegistry.getInstance().register(p, jmxQuorumBean);                    } catch (Exception e) {                        LOG.warn("Failed to register with JMX", e);                        jmxLocalPeerBean = null;                    }                } else {                    RemotePeerBean rBean = new RemotePeerBean(s);                    try {                        MBeanRegistry.getInstance().register(rBean, jmxQuorumBean);                        jmxRemotePeerBean.put(s.id, rBean);                    } catch (Exception e) {                        LOG.warn("Failed to register with JMX", e);                    }                }            }        } catch (Exception e) {            LOG.warn("Failed to register with JMX", e);            jmxQuorumBean = null;        }        try {            /*             * Main loop             */            while (running) {                switch (getPeerState()) {                case LOOKING:                    LOG.info("LOOKING");                    if (Boolean.getBoolean("readonlymode.enabled")) {                        LOG.info("Attempting to start ReadOnlyZooKeeperServer");                        // Create read-only server but don't start it immediately                        final ReadOnlyZooKeeperServer roZk =                            new ReadOnlyZooKeeperServer(logFactory, this, this.zkDb);                        // Instead of starting roZk immediately, wait some grace                        // period before we decide we're partitioned.                        //                        // Thread is used here because otherwise it would require                        // changes in each of election strategy classes which is                        // unnecessary code coupling.                        Thread roZkMgr = new Thread() {                            public void run() {                                try {                                    // lower-bound grace period to 2 secs                                    sleep(Math.max(2000, tickTime));                                    if (ServerState.LOOKING.equals(getPeerState())) {                                        roZk.startup();                                    }                                } catch (InterruptedException e) {                                    LOG.info("Interrupted while attempting to start ReadOnlyZooKeeperServer, not started");                                } catch (Exception e) {                                    LOG.error("FAILED to start ReadOnlyZooKeeperServer", e);                                }                            }                        };                        try {                            roZkMgr.start();                            reconfigFlagClear();                            if (shuttingDownLE) {                                shuttingDownLE = false;                                startLeaderElection();                            }                            setCurrentVote(makeLEStrategy().lookForLeader());                        } catch (Exception e) {                            LOG.warn("Unexpected exception", e);                            setPeerState(ServerState.LOOKING);                        } finally {                            // If the thread is in the the grace period, interrupt                            // to come out of waiting.                            roZkMgr.interrupt();                            roZk.shutdown();                        }                    } else {                        try {                           reconfigFlagClear();                            if (shuttingDownLE) {                               shuttingDownLE = false;                               startLeaderElection();                               }                            setCurrentVote(makeLEStrategy().lookForLeader());                        } catch (Exception e) {                            LOG.warn("Unexpected exception", e);                            setPeerState(ServerState.LOOKING);                        }                                            }                    break;                case OBSERVING:                    try {                        LOG.info("OBSERVING");                        setObserver(makeObserver(logFactory));                        observer.observeLeader();                    } catch (Exception e) {                        LOG.warn("Unexpected exception",e );                    } finally {                        observer.shutdown();                        setObserver(null);                         updateServerState();                    }                    break;                case FOLLOWING:                    try {                       LOG.info("FOLLOWING");                        setFollower(makeFollower(logFactory));                        follower.followLeader();                    } catch (Exception e) {                       LOG.warn("Unexpected exception",e);                    } finally {                       follower.shutdown();                       setFollower(null);                       updateServerState();                    }                    break;                case LEADING:                    LOG.info("LEADING");                    try {                        setLeader(makeLeader(logFactory));                        leader.lead();                        setLeader(null);                    } catch (Exception e) {                        LOG.warn("Unexpected exception",e);                    } finally {                        if (leader != null) {                            leader.shutdown("Forcing shutdown");                            setLeader(null);                        }                        updateServerState();                    }                    break;                }                start_fle = Time.currentElapsedTime();            }        } finally {            LOG.warn("QuorumPeer main thread exited");            MBeanRegistry instance = MBeanRegistry.getInstance();            instance.unregister(jmxQuorumBean);            instance.unregister(jmxLocalPeerBean);            for (RemotePeerBean remotePeerBean : jmxRemotePeerBean.values()) {                instance.unregister(remotePeerBean);            }            jmxQuorumBean = null;            jmxLocalPeerBean = null;            jmxRemotePeerBean = null;        }    }    public Vote lookForLeader() throws InterruptedException {        try {            self.jmxLeaderElectionBean = new LeaderElectionBean();            MBeanRegistry.getInstance().register(                    self.jmxLeaderElectionBean, self.jmxLocalPeerBean);        } catch (Exception e) {            LOG.warn("Failed to register with JMX", e);            self.jmxLeaderElectionBean = null;        }        if (self.start_fle == 0) {           self.start_fle = Time.currentElapsedTime();        }        try {            //准备选举工作            HashMap<Long, Vote> recvset = new HashMap<Long, Vote>();            HashMap<Long, Vote> outofelection = new HashMap<Long, Vote>();            int notTimeout = finalizeWait;            synchronized(this){                logicalclock.incrementAndGet();                updateProposal(getInitId(), getInitLastLoggedZxid(), getPeerEpoch());            }            LOG.info("New election. My id =  " + self.getId() +                    ", proposed zxid=0x" + Long.toHexString(proposedZxid));            //发出通知            sendNotifications();            /*             * Loop in which we exchange notifications until we find a leader             */            //这个循环一直进行直到找到leader            while ((self.getPeerState() == ServerState.LOOKING) &&                    (!stop)){                /*                 * Remove next notification from queue, times out after 2 times                 * the termination time                 */                //接收其它机器到来的通知                Notification n = recvqueue.poll(notTimeout,                        TimeUnit.MILLISECONDS);                /*                 * Sends more notifications if haven't received enough.                 * Otherwise processes new notification.                 */                if(n == null){                    //没有收到反馈就接着发出通知                    if(manager.haveDelivered()){                        sendNotifications();                    } else {                        manager.connectAll();                    }                    /*                     * Exponential backoff                     */                    int tmpTimeOut = notTimeout*2;                    notTimeout = (tmpTimeOut < maxNotificationInterval?                            tmpTimeOut : maxNotificationInterval);                    LOG.info("Notification time out: " + notTimeout);                }  //合法性检验                else if (self.getCurrentAndNextConfigVoters().contains(n.sid)) {                    /*                     * Only proceed if the vote comes from a replica in the current or next                     * voting view.                     */                    switch (n.state) {                    case LOOKING:                        if (getInitLastLoggedZxid() == -1) {                            LOG.debug("Ignoring notification as our zxid is -1");                            break;                        }                        if (n.zxid == -1) {                            LOG.debug("Ignoring notification from member with -1 zxid" + n.sid);                            break;                        }                        // If notification > current, replace and send messages out                        if (n.electionEpoch > logicalclock.get()) {                            logicalclock.set(n.electionEpoch);                            recvset.clear();                            if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,                                    getInitId(), getInitLastLoggedZxid(), getPeerEpoch())) {                                updateProposal(n.leader, n.zxid, n.peerEpoch);                            } else {                                updateProposal(getInitId(),                                        getInitLastLoggedZxid(),                                        getPeerEpoch());                            }                            sendNotifications();                        } else if (n.electionEpoch < logicalclock.get()) {                            if(LOG.isDebugEnabled()){                                LOG.debug("Notification election epoch is smaller than logicalclock. n.electionEpoch = 0x"                                        + Long.toHexString(n.electionEpoch)                                        + ", logicalclock=0x" + Long.toHexString(logicalclock.get()));                            }                            break;                        } else if (totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,                                proposedLeader, proposedZxid, proposedEpoch)) {                            updateProposal(n.leader, n.zxid, n.peerEpoch);                            sendNotifications();                        }                        if(LOG.isDebugEnabled()){                            LOG.debug("Adding vote: from=" + n.sid +                                    ", proposed leader=" + n.leader +                                    ", proposed zxid=0x" + Long.toHexString(n.zxid) +                                    ", proposed election epoch=0x" + Long.toHexString(n.electionEpoch));                        }                        recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));                        if (termPredicate(recvset,                                new Vote(proposedLeader, proposedZxid,                                        logicalclock.get(), proposedEpoch))) {                            // Verify if there is any change in the proposed leader                            while((n = recvqueue.poll(finalizeWait,                                    TimeUnit.MILLISECONDS)) != null){                                if(totalOrderPredicate(n.leader, n.zxid, n.peerEpoch,                                        proposedLeader, proposedZxid, proposedEpoch)){                                    recvqueue.put(n);                                    break;                                }                            }                            /*                             * This predicate is true once we don't read any new                             * relevant message from the reception queue                             */                            if (n == null) {                                self.setPeerState((proposedLeader == self.getId()) ?                                        ServerState.LEADING: learningState());                                Vote endVote = new Vote(proposedLeader,                                        proposedZxid, proposedEpoch);                                leaveInstance(endVote);                                return endVote;                            }                        }                        break;                    case OBSERVING:                        LOG.debug("Notification from observer: " + n.sid);                        break;                    case FOLLOWING:                    case LEADING:                        /*                         * Consider all notifications from the same epoch                         * together.                         */                        if(n.electionEpoch == logicalclock.get()){                            recvset.put(n.sid, new Vote(n.leader, n.zxid, n.electionEpoch, n.peerEpoch));                            if(termPredicate(recvset, new Vote(n.leader,                                            n.zxid, n.electionEpoch, n.peerEpoch, n.state))                                            && checkLeader(outofelection, n.leader, n.electionEpoch)) {                                self.setPeerState((n.leader == self.getId()) ?                                        ServerState.LEADING: learningState());                                Vote endVote = new Vote(n.leader, n.zxid, n.peerEpoch);                                leaveInstance(endVote);                                return endVote;                            }                        }                        /*                         * Before joining an established ensemble, verify that                         * a majority are following the same leader.                         * Only peer epoch is used to check that the votes come                         * from the same ensemble. This is because there is at                         * least one corner case in which the ensemble can be                         * created with inconsistent zxid and election epoch                         * info. However, given that only one ensemble can be                         * running at a single point in time and that each                          * epoch is used only once, using only the epoch to                          * compare the votes is sufficient.                         *                          * @see https://issues.apache.org/jira/browse/ZOOKEEPER-1732                         */                        outofelection.put(n.sid, new Vote(n.leader,                                 IGNOREVALUE, IGNOREVALUE, n.peerEpoch, n.state));                        if (termPredicate(outofelection, new Vote(n.leader,                                IGNOREVALUE, IGNOREVALUE, n.peerEpoch, n.state))                                && checkLeader(outofelection, n.leader, IGNOREVALUE)) {                            synchronized(this){                                logicalclock.set(n.electionEpoch);                                self.setPeerState((n.leader == self.getId()) ?                                        ServerState.LEADING: learningState());                            }                            Vote endVote = new Vote(n.leader, n.zxid, n.peerEpoch);                            leaveInstance(endVote);                            return endVote;                        }                        break;                    default:                        LOG.warn("Notification state unrecoginized: " + n.state                              + " (n.state), " + n.sid + " (n.sid)");                        break;                    }                } else {                    LOG.warn("Ignoring notification from non-cluster member " + n.sid);                }            }            return null;        } finally {            try {                if(self.jmxLeaderElectionBean != null){                    MBeanRegistry.getInstance().unregister(                            self.jmxLeaderElectionBean);                }            } catch (Exception e) {                LOG.warn("Failed to unregister with JMX", e);            }            self.jmxLeaderElectionBean = null;        }    }

英文注释写的比较清晰,不太需要加注释了。接下来会关注QuorumPeer的对外服务,以及机器间通信相关代码

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 偏头疼恶心想吐怎么办 健康证怎么办 在哪办 怎么办健康证去哪里办 公司合同不给我怎么办 孕妇吃了酸梅粉怎么办 婧氏牙膏没客源怎么办 乐视手机耗电快怎么办 乐视手机费电快怎么办 最爱最恨都是你怎么办 耳朵长疱疹很痛怎么办 刚怀孕就有霉菌怎么办 车牌选错了想换怎么办 足癣传染到身上怎么办 金鱼生病了立鳞怎么办 脸上有闭口痘痘怎么办 泰迪得了皮肤癣怎么办 qq截图发不出去怎么办 半夜2点肚子饿怎么办 半夜两三点饿了怎么办 科目三预约不上怎么办 心脏支架又堵了怎么办 车辆验车过期了怎么办 车辆年审过期2天怎么办 违停单子丢了怎么办 沙发弹簧包坏了怎么办 bt种子被和谐了怎么办 苹果手机id密码忘了怎么办 墙漆颜色太深了怎么办 油漆颜色太深了怎么办 墙面漆颜色太深怎么办 古代打仗牙掉了怎么办 乐视电视没声音怎么办 老公疑心病很重怎么办啊 被安装了尿道锁怎么办 狼青小狗腿罗圈怎么办 备孕期间有霉菌怎么办 虫子进皮肤里了怎么办 生完孩子肚子越来越大怎么办 怀孕8个月肚子小怎么办 孕晚期胎儿不长怎么办 肚子上肉特别多怎么办