最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Zookeeper實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能

 更新時(shí)間:2023年09月07日 10:12:43   作者:叫我二蛋  
無(wú)論是采用SOA還是微服務(wù)架構(gòu),都需要使用服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)組件,本文將基于 Zookeeper 實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能,如果跟我一樣有同樣的困惑,希望可以通過(guò)本文了解其他組件如何使用 Zookeeper 作為注冊(cè)中心的工作原理

前言

無(wú)論是采用SOA還是微服務(wù)架構(gòu),都需要使用服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)組件。我剛開始接觸 Dubbo 時(shí)一直對(duì)服務(wù)注冊(cè)/發(fā)現(xiàn)以及 Zookeeper 的作用感到困惑,現(xiàn)在看來(lái)是因?yàn)閷?duì)分布式系統(tǒng)的理解不夠深入,對(duì) Dubbo 和 Zookeeper 的工作原理不夠清楚。

本文將基于 Zookeeper 實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能,如果跟我一樣有同樣的困惑,希望可以通過(guò)本文了解其他組件如何使用 Zookeeper 作為注冊(cè)中心的工作原理。

聲明

文章中所提供的代碼僅供參考,旨在幫助缺乏基礎(chǔ)知識(shí)的開發(fā)人員更好地理解服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)的概念。請(qǐng)注意,這些代碼并不適用于實(shí)際應(yīng)用中

前置知識(shí)

服務(wù)注冊(cè)和發(fā)現(xiàn)

在SOA或微服務(wù)架構(gòu)中,由于存在大量的服務(wù)以及可能的相互調(diào)用,為了更有效地管理這些服務(wù),我們通常需要引入一個(gè)統(tǒng)一的地方,即注冊(cè)中心,來(lái)集中管理它們,而注冊(cè)中心最基本的功能就是服務(wù)注冊(cè)/發(fā)現(xiàn)。

  • 服務(wù)注冊(cè):將該服務(wù)實(shí)例的元數(shù)據(jù)(如IP地址、端口號(hào)、健康狀態(tài)等)注冊(cè)到注冊(cè)中心,這樣其他服務(wù)或客戶端可以發(fā)現(xiàn)和使用該服務(wù)。
  • 服務(wù)發(fā)現(xiàn):當(dāng)一個(gè)服務(wù)需要調(diào)用別的服務(wù)時(shí),使用靜態(tài)配置是不可行的,這個(gè)時(shí)候可以去注冊(cè)中心獲取可用的服務(wù)實(shí)例并調(diào)用。

Zookeeper

Zookeeper 是一個(gè)傳統(tǒng)的分布式協(xié)調(diào)服務(wù),它更多的被用來(lái)作為一個(gè)協(xié)調(diào)器使用,比如來(lái)協(xié)調(diào)管理 Hadoop 集群、協(xié)調(diào) Kafka 的 leader 選舉等。

為什么會(huì)有組件將其視為一個(gè)注冊(cè)中心使用?我想有幾個(gè)原因:

  1. Zookeeper 在分布式系統(tǒng)中具有更強(qiáng)的一致性和可靠性,可以確保各個(gè)服務(wù)的注冊(cè)信息保持一致。
  2. Zookeeper 使用內(nèi)存存儲(chǔ)數(shù)據(jù),具有很高的讀寫性能。這對(duì)于注冊(cè)中心來(lái)說(shuō)非常關(guān)鍵,因?yàn)樗枰焖俚仨憫?yīng)客戶端的請(qǐng)求。
  3. Zookeeper 的 Watcher 機(jī)制可以讓客戶端監(jiān)聽指定節(jié)點(diǎn)的變化。當(dāng)某個(gè)節(jié)點(diǎn)(注冊(cè)中心)發(fā)生變化時(shí),Zookeeper 可以通知其他服務(wù)實(shí)現(xiàn)實(shí)時(shí)更新。

工作原理

以下圖為例,可以看到 Dubbo 是如何使用 Zookeeper 實(shí)現(xiàn)服務(wù)注冊(cè)/發(fā)現(xiàn)的。

  • 服務(wù)提供者向 /dubbo/com.foo.BarService/providers 目錄下寫入自己的 URL 地址。
  • 服務(wù)消費(fèi)者訂閱 /dubbo/com.foo.BarService/providers 目錄下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目錄下寫入自己的 URL 地址。

這里的目錄就是 Zookeeper 的數(shù)據(jù)結(jié)構(gòu),原理非常簡(jiǎn)單,本質(zhì)上就是服務(wù)提供者和消費(fèi)者按照約定在 Zookeeper 上讀寫數(shù)據(jù),同時(shí)借用其 Watcher 機(jī)制、臨時(shí)節(jié)點(diǎn)和可靠性等特性高效的實(shí)現(xiàn)以下功能:

  • 當(dāng)提供者服務(wù)出現(xiàn)斷電等異常停機(jī)時(shí),注冊(cè)中心能自動(dòng)刪除提供者信息。
  • 當(dāng)注冊(cè)中心重啟時(shí),能自動(dòng)恢復(fù)注冊(cè)數(shù)據(jù)以及訂閱請(qǐng)求。

實(shí)現(xiàn)過(guò)程

注冊(cè)中心

下面通過(guò) Zookeeper 的 Java API 實(shí)現(xiàn)一個(gè)只包含服務(wù)注冊(cè)/發(fā)現(xiàn)的注冊(cè)中心,代碼如下:

public class RegistrationCenter {
    // 連接信息
    private String connectString = "192.168.10.11:2181,192.168.10.11:2182,192.168.10.11:2183";
    // 超時(shí)時(shí)間
    private int sessionTimeOut = 30000;
    private final String ROOT_PATH = "/servers";
    private ZooKeeper client;
    public RegistrationCenter() {
        this(null);
    }
    public RegistrationCenter(Consumer<List<String>> consumer) {
        try {
            getConnection(null == consumer ? null : watchedEvent -> {
                //監(jiān)聽服務(wù)器地址的上下線
                if (watchedEvent.getType() == Watcher.Event.EventType.NodeChildrenChanged) {
                    try {
                        consumer.accept(subServers());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            Stat stat = client.exists(ROOT_PATH, false);
            if (stat == null) {
                //創(chuàng)建根節(jié)點(diǎn)
                client.create(ROOT_PATH, ROOT_PATH.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * @param serverName 將服務(wù)器注冊(cè)到zk集群時(shí),所需的服務(wù)名稱
     * @param metadata   服務(wù)元數(shù)據(jù)
     * @throws Exception
     */
    public void doRegister(String serverName, Metadata metadata) throws Exception {
        /**
         * ZooDefs.Ids.OPEN_ACL_UNSAFE: 此權(quán)限表示允許所有人訪問(wèn)該節(jié)點(diǎn)(服務(wù)器)
         * CreateMode.EPHEMERAL_SEQUENTIAL: 由于服務(wù)器是動(dòng)態(tài)上下線的,上線后存在,下線后不存在,所以是臨時(shí)節(jié)點(diǎn)
         * 而服務(wù)器一般都是有序號(hào)的,所以是臨時(shí)、有序的節(jié)點(diǎn).
         */
        String node = client.create(ROOT_PATH + "/" + serverName, metadata.toString().getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
        System.out.println(serverName + " 已經(jīng)上線");
    }
    /**
     * 發(fā)現(xiàn)/訂閱服務(wù)
     */
    public List<String> subServers() throws InterruptedException, KeeperException {
        List<String> zkChildren = client.getChildren(ROOT_PATH, true);
        List<String> servers = new ArrayList<>();
        zkChildren.forEach(node -> {
            //拼接服務(wù)完整信息
            try {
                byte[] data = client.getData(ROOT_PATH + "/" + node, false, null);
                servers.add(new String(data));
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return servers;
    }
    private void getConnection(Watcher watcher) throws IOException {
        this.client = new ZooKeeper(connectString, sessionTimeOut, watcher);
    }
    /**
     * 服務(wù)元數(shù)據(jù)
     */
    public static class Metadata {
        public Metadata() {
        }
        public Metadata(String ip, int port) {
            this.ip = ip;
            this.port = port;
        }
        private String ip;
        private int port;
        public String getIp() {
            return ip;
        }
        public void setIp(String ip) {
            this.ip = ip;
        }
        public int getPort() {
            return port;
        }
        public void setPort(int port) {
            this.port = port;
        }
        @Override
        public String toString() {
            return "{" + "ip='" + ip + '\'' + ", port=" + port + '}';
        }
    }
}

該類中兩個(gè)核心方法:doRegister()、subServers() 服務(wù)注冊(cè)和訂閱。

  • doRegister()主要是往 Zookeeper 中創(chuàng)建了一個(gè)臨時(shí)節(jié)點(diǎn)數(shù)據(jù),臨時(shí)節(jié)點(diǎn)的優(yōu)勢(shì)就是當(dāng)服務(wù)出現(xiàn)斷電等異常停機(jī)時(shí),節(jié)點(diǎn)會(huì)自動(dòng)刪除。
  • subServers()則是去 Zookeeper 讀取了所有服務(wù)提供者的信息,并且監(jiān)聽了節(jié)點(diǎn)狀態(tài),當(dāng)節(jié)點(diǎn)發(fā)生創(chuàng)建、刪除、更新等事件時(shí)重新獲取服務(wù)者的信息,做到數(shù)據(jù)實(shí)時(shí)更新。

至此,一個(gè)簡(jiǎn)單的注冊(cè)中心就完成了,當(dāng)然,如果要實(shí)現(xiàn)一個(gè)成熟的注冊(cè)中心,還要考慮負(fù)載均衡、高可用性和容錯(cuò)、服務(wù)治理和路由控制等功能,這里先不展開。

服務(wù)注冊(cè)

當(dāng)有了注冊(cè)中心,服務(wù)提供者就可以調(diào)用 doRegister() 進(jìn)行注冊(cè),代碼如下:

public class ProviderServer {
    public static void main(String[] args) throws Exception {
        RegistrationCenter registrationCenter = new RegistrationCenter();
        registrationCenter.doRegister("provider", new RegistrationCenter.Metadata("127.0.0.1", 8080));
        Thread.sleep(Long.MAX_VALUE);
    }
}

服務(wù)發(fā)現(xiàn)

同樣,服務(wù)消費(fèi)者可以調(diào)用 subServers() 發(fā)現(xiàn)服務(wù)提供者,同時(shí)當(dāng)服務(wù)提供者發(fā)生變化時(shí)會(huì)通知到消費(fèi)者。代碼如下:

public class ConsumerServer {
    public static void main(String[] args) throws Exception {
        RegistrationCenter registrationCenter = new RegistrationCenter(newServers -> {
            System.out.println("服務(wù)更新了..."+newServers);
        });
        List<String> servers = registrationCenter.subServers();
        System.out.println(servers);
        Thread.sleep(Long.MAX_VALUE);
    }
}

總結(jié)

服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能是為了解決分布式系統(tǒng)中的服務(wù)管理和通信問(wèn)題而設(shè)計(jì)的,經(jīng)過(guò)不斷的發(fā)展與負(fù)載均衡、健康監(jiān)測(cè)、服務(wù)治理和路由控制等功能完善成為一個(gè)注冊(cè)中心。服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)有助于實(shí)現(xiàn)系統(tǒng)的彈性和可擴(kuò)展性,因?yàn)樾碌姆?wù)實(shí)例可以動(dòng)態(tài)地加入系統(tǒng),而無(wú)需手動(dòng)配置和修改已有的代碼。

以上就是基于Zookeeper實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能的詳細(xì)內(nèi)容,更多關(guān)于Zookeeper服務(wù)注冊(cè)和發(fā)現(xiàn)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java實(shí)現(xiàn)掃雷游戲詳細(xì)代碼講解

    Java實(shí)現(xiàn)掃雷游戲詳細(xì)代碼講解

    windows自帶的游戲《掃雷》是陪伴了無(wú)數(shù)人的經(jīng)典游戲,本文將利用Java語(yǔ)言實(shí)現(xiàn)這一經(jīng)典的游戲,文中的示例代碼講解詳細(xì),感興趣的可以學(xué)習(xí)一下
    2022-05-05
  • Maven編譯錯(cuò)誤:程序包c(diǎn)om.sun.*包不存在的三種解決方案

    Maven編譯錯(cuò)誤:程序包c(diǎn)om.sun.*包不存在的三種解決方案

    J2SE中的類大致可以劃分為以下的各個(gè)包:java.*,javax.*,org.*,sun.*,本文文章主要介紹了maven編譯錯(cuò)誤:程序包c(diǎn)om.sun.xml.internal.ws.spi不存在的解決方案,感興趣的可以了解一下
    2024-02-02
  • SpringBoot+fileUpload獲取文件上傳進(jìn)度

    SpringBoot+fileUpload獲取文件上傳進(jìn)度

    這篇文章主要為大家詳細(xì)介紹了SpringBoot+fileUpload獲取文件上傳進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • Java實(shí)現(xiàn)短信驗(yàn)證碼和國(guó)際短信群發(fā)功能的示例

    Java實(shí)現(xiàn)短信驗(yàn)證碼和國(guó)際短信群發(fā)功能的示例

    本篇文章主要介紹了Java實(shí)現(xiàn)短信驗(yàn)證碼和國(guó)際短信群發(fā)功能的示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-02-02
  • java基于雙向環(huán)形鏈表解決丟手帕問(wèn)題的方法示例

    java基于雙向環(huán)形鏈表解決丟手帕問(wèn)題的方法示例

    這篇文章主要介紹了java基于雙向環(huán)形鏈表解決丟手帕問(wèn)題的方法,簡(jiǎn)單描述了丟手帕問(wèn)題,并結(jié)合實(shí)例形式給出了Java基于雙向環(huán)形鏈表解決丟手帕問(wèn)題的步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-11-11
  • spring boot metrics監(jiān)控指標(biāo)使用教程

    spring boot metrics監(jiān)控指標(biāo)使用教程

    這篇文章主要為大家介紹了針對(duì)應(yīng)用監(jiān)控指標(biāo)暴露spring boot metrics監(jiān)控指標(biāo)的使用教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-02-02
  • Java中Cglib代理類重寫邏輯詳解

    Java中Cglib代理類重寫邏輯詳解

    這篇文章主要介紹了Java中Cglib代理類重寫邏輯詳解,代理類中只會(huì)維護(hù)NoOp這個(gè)回調(diào)屬性,并不會(huì)生成目標(biāo)類MyService中的noOp所對(duì)應(yīng)的方法,需要的朋友可以參考下
    2023-11-11
  • rocketmq如何修改存儲(chǔ)路徑

    rocketmq如何修改存儲(chǔ)路徑

    這篇文章主要介紹了rocketmq如何修改存儲(chǔ)路徑的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 解決IDEA2020.2插件lombok報(bào)錯(cuò)問(wèn)題(親測(cè)有效)

    解決IDEA2020.2插件lombok報(bào)錯(cuò)問(wèn)題(親測(cè)有效)

    這篇文章主要介紹了解決IDEA2020.2插件lombok報(bào)錯(cuò)問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-08-08
  • 在SpringBoot的yml配置文件中讀取Windows系統(tǒng)環(huán)境變量的方法

    在SpringBoot的yml配置文件中讀取Windows系統(tǒng)環(huán)境變量的方法

    本文介紹了在SpringBoot的application.yml配置文件中使用${VARIABLE_NAME}占位符引用Windows系統(tǒng)環(huán)境變量的方法,并提供了設(shè)置默認(rèn)值、在Java代碼中獲取環(huán)境變量值的建議,同時(shí),文章詳細(xì)講述了如何通過(guò)系統(tǒng)設(shè)置和命令行設(shè)置環(huán)境變量,需要的朋友可以參考下
    2026-03-03

最新評(píng)論

罗城| 贞丰县| 曲周县| 白河县| 亳州市| 红安县| 梁山县| 大冶市| 抚州市| 内丘县| 龙游县| 长宁区| 格尔木市| 北安市| 金阳县| 乳山市| 永泰县| 清苑县| 新密市| 旌德县| 鄂托克旗| 三原县| 高尔夫| 临江市| 确山县| 吴川市| 清镇市| 平利县| 大理市| 商城县| 永宁县| 威海市| 大理市| 卢龙县| 宾阳县| 新乡县| 永城市| 通州市| 巴青县| 滦南县| 安溪县|