基於 ZooKeeper 實現爬蟲叢集的監控

coyan發表於2021-09-09

ZooKeeper

zookeeper.png

ZooKeeper 是一個開源的分散式協調服務,ZooKeeper框架最初是在“Yahoo!"上構建的,用於以簡單而穩健的方式訪問他們的應用程式。 後來,Apache ZooKeeper成為Hadoop,HBase和其他分散式框架使用的有組織服務的標準。 例如,Apache HBase使用ZooKeeper跟蹤分散式資料的狀態。ZooKeeper 的設計目標是將那些複雜且容易出錯的分散式一致性服務封裝起來,構成一個高效可靠的原語集,並以一系列簡單易用的介面提供給使用者使用。

ZooKeeper 通常用於:命名服務、配置管理、叢集管理、分散式協調/通知、分散式鎖和分散式佇列等等。

各個爬蟲的節點通過註冊到 ZooKeeper 從而實現爬蟲叢集的管理。NetDiscovery 正是藉助了 ZooKeeper 的特性來監控爬蟲叢集。

NetDiscovery 是一款基於 Vert.x、RxJava 2 等框架實現的通用爬蟲框架。它包含了豐富的特性

爬蟲叢集的監控

NetDiscovery 包含了 Spider 和 SpiderEngine。 Spider 用於實現爬蟲的業務邏輯,Spider 可以新增到 SpiderEngine,由 SpiderEngine 來管理各個 Spider 的生命週期。

但是 SpiderEngine 部署到每一個節點之後,SpiderEngine 如何進行監控和管理呢?

可以將 SpiderEngine 在執行時,先註冊到 ZooKeeper。(需要事先在 ZooKeeper 叢集建立 /netdiscovery 節點)


    /**
     * 啟動SpiderEngine中所有的spider,讓每個爬蟲並行執行起來。
     *
     */
    public void run() {

        if (Preconditions.isNotBlank(spiders)) {

            registerZK();
            ......  
        }
    }

    /**
     * 將當前 SpiderEngine 註冊到 zookeeper 指定的目錄 /netdiscovery 下
     */
    private void registerZK() {

        if (Preconditions.isNotBlank(zkStr) && useZk) {
            log.info("zkStr: {}", zkStr);

            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000,3);
            CuratorFramework client = CuratorFrameworkFactory.newClient(zkStr, retryPolicy);
            client.start();
            try {
                String ipAddr = InetAddress.getLocalHost().getHostAddress() + "-" + defaultHttpdPort + "-" + System.currentTimeMillis();
                String nowSpiderEngineZNode = "/netdiscovery/" + ipAddr;
                client.create().withMode(CreateMode.EPHEMERAL).forPath(nowSpiderEngineZNode,nowSpiderEngineZNode.getBytes());
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
複製程式碼

另外,需要使用 NetDiscovery Monitor 的 CuratorManager 類。 它藉助 Zookeeper 的 Watcher 機制,監聽已經註冊到 /netdiscovery 這個父 zNode 下的各個子 zNode ,也就是各個 SpiderEngine。

Watcher機制是指 ZooKeeper 客戶端向 ZooKeeper 伺服器註冊 Watcher 的同時,會將 Watcher 物件儲存在客戶端的 WatchManager 中。ZooKeeper 伺服器觸發 Watcher 事件後,會向客戶端傳送通知,客戶端執行緒從 WatchManager 中回撥 Watcher 執行相應的功能。

    /**
     * 當前所監控的父的 zNode 下若是子 zNode 發生了變化:新增,刪除,修改
     * <p>
     * 下述方法都會觸發執行
     *
     * @param event
     */
    @Override
    public void process(WatchedEvent event) {

        List<String> newZodeInfos = null;
        try {
            newZodeInfos = client.getChildren().usingWatcher(this).forPath("/netdiscovery");
            //根據初始化容器的長度與最新的容器的長度進行比對,就可以推匯出當前 SpiderEngine 叢集的狀態:新增,當機/下線,變更...
            //哪個容器中元素多,就迴圈遍歷哪個容器。
            if (Preconditions.isNotBlank(newZodeInfos)) {
                if (newZodeInfos.size()>allZnodes.size()){
                    //明確顯示新增了哪個 SpiderEngine 節點
                    for (String nowZNode:newZodeInfos) {
                        if (!allZnodes.contains(nowZNode)){
                            log.info("新增 SpiderEngine 節點{}", nowZNode);
                        }
                    }
                }else if (newZodeInfos.size()<allZnodes.size()){
                    // 當機/下線
                    // 明確顯示哪個 SpiderEngine 節點當機/下線了
                    for (String initZNode : allZnodes) {
                        if (!newZodeInfos.contains(initZNode)) {
                            log.info("SpiderEngine 節點【{}】下線了!", initZNode);

                            // 如果有下線的處理,則處理(例如發郵件、簡訊等)
                            if (serverOfflineProcess!=null) {
                                serverOfflineProcess.process();
                            }
                        }
                    }
                }else {
                    // SpiderEngine 叢集正常執行;
                    // 當機/下線了,當時馬上重啟了,總的爬蟲未發生變化
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        allZnodes = newZodeInfos;
    }
複製程式碼

所以需要單獨執行一個程式,例如:

public class TestCuratorManager {

    public static void main(String[] args) {

        CuratorManager curatorManager = new CuratorManager();
        curatorManager.start();
    }
}
複製程式碼

下圖反映了 ZooKeeper 如何監控 SpiderEngine 叢集。

SpiderEngine+ZK.png

總結

爬蟲框架 github 地址:github.com/fengzhizi71…

本文介紹瞭如何使用 ZooKeeper 來監控爬蟲的叢集。未來,NetDiscovery 還會增加更為通用的功能。


Java與Android技術棧:每週更新推送原創技術文章,歡迎掃描下方的公眾號二維碼並關注,期待與您的共同成長和進步。

基於 ZooKeeper 實現爬蟲叢集的監控

相關文章