zookeeper-curator-leaderSelector

constructor

executorService thread pool to use  線程池/默認線程池爲守護線程
     * @param listener        listener   LeaderSelectorListener 監聽器
     */
    public LeaderSelector(CuratorFramework client, String leaderPath, CloseableExecutorService executorService, LeaderSelectorListener listener)
    {
        //省略參數校驗
        this.client = client;
        this.listener = new WrappedListener(this, listener);
        hasLeadership = false;

        this.executorService = executorService;
        mutex = new InterProcessMutex(client, leaderPath)  //zookeeper 維護的鎖
        {
            @Override
            protected byte[] getLockNodeBytes()
            {
                return (id.length() > 0) ? getIdBytes(id) : null;
            }
        };
    }

start

 /**
     * Attempt leadership. This attempt is done in the background - i.e. this method returns
     * immediately.<br><br>
     * <b>IMPORTANT: </b> previous versions allowed this method to be called multiple times. This
     * is no longer supported. Use {@link #requeue()} for this purpose.
     */
    public void start()
    {
        //省略參數校驗
         client.getConnectionStateListenable().addListener(listener);  //監聽連接狀態改變
        requeue();   //重新排隊
    }

internalRequeue

  //同一個leaderSelect保證只有一個競爭
 private synchronized boolean internalRequeue()
    {
        if ( !isQueued && (state.get() == State.STARTED) ) 
        {
            isQueued = true;    
            //future返回空參,異步
            Future<Void> task = executorService.submit(new Callable<Void>()
            {
                @Override
                public Void call() throws Exception
                {
                    try
                    {
                        doWorkLoop();   //真正的獲取leader
                    }
                    finally
                    {
                        clearIsQueued();
                        //開啓自動重新排隊,會一直競爭leader
                        if ( autoRequeue.get() )  
                        {
                            internalRequeue();
                        }
                    }
                    return null;
                }
            });
            ourTask.set(task);

            return true;
        }
        return false;
    }

doWork

    @VisibleForTesting
    void doWork() throws Exception
    {
        hasLeadership = false;
        try
        {
            //嘗試獲取鎖
            mutex.acquire();  
            //在整個acquire 到release 爲leader狀態
            hasLeadership = true;  
            try
            {
                if ( debugLeadershipLatch != null )
                {
                    debugLeadershipLatch.countDown();
                }
                if ( debugLeadershipWaitLatch != null )
                {
                    debugLeadershipWaitLatch.await();
                }
                //保證同一個path下的任意leaderSeclector,只有一個listen執行此業務代碼
                listener.takeLeadership(client);   
            }
            catch ( InterruptedException e )
            {
                Thread.currentThread().interrupt();
                throw e;
            }
            catch ( Throwable e )
            {
                ThreadUtils.checkInterrupted(e);
            }
            finally
            {
                clearIsQueued();
            }
        }
        catch ( InterruptedException e )
        {
            Thread.currentThread().interrupt();
            throw e;
        }
        finally
        {
            if ( hasLeadership )
            {
                hasLeadership = false;
                try
                {
                    mutex.release();  //釋放鎖
                }
                catch ( Exception e )
                {
                    ThreadUtils.checkInterrupted(e);
                    log.error("The leader threw an exception", e);
                    // ignore errors - this is just a safety
                }
            }
        }
    }
發佈了72 篇原創文章 · 獲贊 9 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章