利用zookeeper構建高可用的Spring服務

高可用是一個健壯的系統必備的特性,實現高可用的方法有很多,這篇文章簡要介紹了實現高可用的方法,適合瀏覽一遍熟悉高可用的概況。
我的這篇文章的主要目的是介紹如何用zookeeper構建一個高可用的Spring服務,項目的代碼也放在了我的github上。

Spring服務的高可用

我瞭解的Spring服務實現高可用的方式有負載均衡主從模式

利用負載均衡機制將請求發送到不同的微服務實例上,這種機制要求各個服務必須是無狀態的,這樣當一個請求過來的時候才能保證無論發到哪個微服務實例上都能得到一致的結果。

但是如果一個服務的業務要求它是有狀態的(比如在服務中配置了定時器區完成定時任務),這時利用負載均衡就不能實現高可用的要求,比如在我們部署了兩個微服務實例,兩個服務中接收請求、記錄請求到數據庫並啓動定時器任務,這時如果一個服務崩潰了,它上面的定時任務也隨之消失,這時我們希望復原這些定時任務,但是當讀取數據庫時,我們並不知道原來崩潰的服務上有哪些定時任務。(當然原則上如果在數據庫中增加一個記錄服務實例的字段,是可以實現的,但是這樣會讓結構很複雜)

如果採用主從模式的高可用,將所有的定時任務都放在一個服務上,這樣當一個服務崩潰時,另一個服務監聽到這個消息,就會從數據庫中讀取所有的任務記錄並啓動定時任務。這樣的模式結構更簡單清晰。

Zookeeper簡介

在Zookeeper的官網上有這麼一句話:ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.
這大概描述了Zookeeper主要可以幹哪些事情:配置管理、名字服務、分佈式同步以及集羣管理。比較具體的介紹請參見ZooKeeper簡介(淺入),我們這裏配置服務的主從主要是利用了其group services的功能。

如果沒有使用過的同學想實際體驗一下,推薦按照ZooKeeper Getting Started Guide官網上的demo操作一遍,5min左右的時間,可以對zookeeper的基本用法有個瞭解。

代碼實現

完整的代碼實現可以到我的github上查看,我這裏介紹實現高可用主從模式的幾個關鍵地方。

Curator是Netflix公司開源的一套zookeeper客戶端框架,解決了很多Zookeeper客戶端非常底層的細節開發工作,包括連接重連、反覆註冊Watcher和NodeExistsException異常等等。具體的使用方法這裏不做展開,有興趣的可以參考Zookeeper客戶端Curator使用詳解

我們可以使用如下curatorFramework()的方法便捷的建立服務與zookeeper的連接。

    @Bean(destroyMethod = "close")
    public CuratorFramework curatorFramework() {
        return CuratorFrameworkFactory.builder().connectString(zkUrl).retryPolicy(new ExponentialBackoffRetry(1000, 3)).sessionTimeoutMs(5000).connectionTimeoutMs(5000).build();
    }

    @Bean(destroyMethod = "stop")
    public LeaderInitiatorFactoryBean leaderInitiator() {
        LeaderInitiatorFactoryBean bean = new LeaderInitiatorFactoryBean();
        bean.setClient(curatorFramework()).setPath(path).setRole(role).setApplicationEventPublisher(applicationEventPublisher);
        return bean;
    }

    @Bean(destroyMethod = "stop")
    public ZookeeperMetadataStore zookeeperMetadataStore() throws Exception {
        ZookeeperMetadataStore metadataStore = new ZookeeperMetadataStore(curatorFramework());
        metadataStore.setRoot(path);
        return metadataStore;
    }

同時爲了實現服務的主從機制,引入spring-integration-zookeeper依賴,用leaderInitiator()方法將服務配置成主從模式,當主服務發生問題時,spring會通過自己的事件廣播器將這個消息傳遞給從服務,從服務在接收到事件之後會執行一些方法,將自己的狀態更新成主服務。監聽器的實現如下:

    @EventListener
    public void processEvent(AbstractLeaderEvent event) {
        if (event instanceof OnGrantedEvent) {
            logger.info("on grant:" + event);
            haService.leaderGranted();
            logger.info(" leader grant process succeed");
        } else if (event instanceof OnRevokedEvent) {
            logger.info("on revoke:" + event);
            haService.leaderRevoked();
            logger.info(" leader revoke process succeed");
        }
    }

以上是利用zookeeper構建高可用的Spring服務的一個簡單demo,完整代碼可以到我的github上查看,如果對你有幫助希望你能在博客和github上幫我點贊!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章