RPC 框架使用 Etcd 作為注冊中心

本文將介紹的是我們自研的RPC框架Dapeng-soa(https://github.com/dapeng-soa/dapeng-soa),使用 etcd 作為新的注冊中心的一種方案

Dapeng注冊中心節(jié)點

基本根節(jié)點

/soa/runtime/services
/soa/config/services
/soa/config/routes

節(jié)點目錄圖


├── soa
│   ├── runtime
│   │   │   ├── services
│   │   │   │   └── com.today.service.goods.GoodsService 
│   │   │   │                                       └── 192.168.10.121:9071
                                                   └── 192.168.10.121:9072
                                                   └── 192.168.10.121:9073
                                                   └── 192.168.10.121:9074
│   ├── config
│   │   │   ├── services
│   │   │   │   └── com.today.service.goods.GoodsService 
│   │   │   │                                       └──

│   │   │   ├── routes
│   │   │   │   └── com.today.service.goods.GoodsService 
  • 1.除了帶有IP,端口信息的節(jié)點為臨時節(jié)點(相對于zk),其他均為永久性節(jié)點
  • 2.zk類似與文件系統(tǒng)庵芭,父節(jié)點,子節(jié)點的模式闹蒜。192.168.10.121:9071在zk中為一個臨時子節(jié)點
  • 3.etcd是以key-value形式進(jìn)行存儲的,/soa/runtime/services//soa/runtime/services/com.UserService對應(yīng)etcd中的兩個key,他們之間沒有什么聯(lián)系抑淫,只有在查詢key時绷落,指定--prefix時,會根據(jù)前綴進(jìn)行搜尋key

etcd租約節(jié)點 實現(xiàn)類似zookeeper的臨時節(jié)點方案

  • 1.etcd使用租約的方式,對創(chuàng)建的key設(shè)置超時時間,當(dāng)超時時,該節(jié)點就會被刪除始苇。
  • 2.我們可以為此節(jié)點續(xù)租,當(dāng)節(jié)點即將超時時砌烁,就進(jìn)行續(xù)租。這樣就可以達(dá)到類似于zookeeper臨時節(jié)點的作用。
  • 3.當(dāng)客戶端由于什么原因掛掉以后,etcd上的節(jié)點由于沒有被繼續(xù)續(xù)租函喉,很快就會到期被刪除避归。

Java客戶端實現(xiàn)租約與續(xù)租的代碼邏輯

public Main(String registryAddress, String host) {
        Client client = Client.builder().endpoints(registryAddress).build();
        this.lease = client.getLeaseClient();
        this.kv = client.getKVClient();
        try {
            this.leaseId = lease.grant(5).get().getID();
        } catch (Exception e) {
            LOGGER.error(e.getMessage(), e);
        }

        keepAlive();

        try {
            int port = 1000;
            register("com.DemoService", host, port + 50);
            logger.info("provider-agent provider register to etcd at port {}", port + 50);
        } catch (Exception e) {
           logger.error(e.getMessage,e);
        }
    }

    /**
     * 向 ETCD 中注冊服務(wù)
     */
    public void register(String serviceName, String host, int port) throws Exception {
        String strKey = MessageFormat.format("/{0}/{1}/{2}:{3}", rootPath, serviceName, host, String.valueOf(port));
        ByteSequence key = ByteSequence.fromString(strKey);
        String weight = "50";
        ByteSequence val = ByteSequence.fromString(weight);


        kv.put(key, val, PutOption.newBuilder().withLeaseId(leaseId).withPrevKV().build()).get();
        kv.txn();
        logger.info("Register a new service at:{},weight:{}", strKey, weight);
    }

    /**
     * 發(fā)送心跳到ETCD,表明該host是活著的
     */
    public void keepAlive() {
        Executors.newSingleThreadExecutor().submit(
                () -> {
                    try {
                        Lease.KeepAliveListener listener = lease.keepAlive(leaseId);
                        listener.listen();
                        logger.info("KeepAlive lease:" + leaseId + "; Hex format:" + Long.toHexString(leaseId));
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
        );
    }
  • 1.通過this.leaseId = lease.grant(5).get().getID();注冊租約,然后再注冊服務(wù)到etcd上時,使用該租約.
  • 2.keepAlive()方法保持客戶端與etcd的聯(lián)系管呵,并對租約進(jìn)行續(xù)租梳毙,一旦將要超時時,馬上就行續(xù)租捐下。
  • 3.當(dāng)客戶端掉線或者關(guān)閉后账锹,keepAlive將不會繼續(xù)續(xù)租,5s后坷襟,租約到期奸柬,節(jié)點就會被刪除.

etcd有序節(jié)點與zookeepr有序節(jié)點

  • 1.zookeeper臨時節(jié)點會在節(jié)點最后生成一個序列串,在相同父節(jié)點下每次創(chuàng)建子節(jié)點時啤握,節(jié)點最后的序列串會有序遞增
  • 2.etcd創(chuàng)建的每一個節(jié)點都會帶有如下幾個信息:
message KeyValue {
  bytes key = 1;
  int64 create_revision = 2;
  int64 mod_revision = 3;
  int64 version = 4;
  bytes value = 5;
  int64 lease = 6;
}
  • 1.etcd服務(wù)段有一個機(jī)制鸟缕,他會對每一次請求創(chuàng)建的任何key提供create_revision和mod_revision的遞增,遞增時全局性的排抬,任何key的操作都會在全局的舉出上面進(jìn)行遞增。

  • 2.那么在服務(wù)節(jié)點下授段,我們每一次創(chuàng)建一個key時,Create_Revision都會在之前最后創(chuàng)建的節(jié)點的基礎(chǔ)上增加1蹲蒲。

  • 3.每一次修改一個key的內(nèi)容時,mod_Revision就會在全局計數(shù)器上增加一次。

結(jié)論侵贵,etcd的key支持天然的有序性届搁。可以根據(jù)這兩個屬性來判斷key創(chuàng)建的先后順序窍育。

etcd watch機(jī)制

  • 1.zookeeperwatch機(jī)制時一次性的卡睦,當(dāng)watch的節(jié)點發(fā)生變更后,會通知客戶端漱抓,同時watch失效
  • 2.etcdwatch機(jī)制時一直生效的表锻,watch一次,一直可以得到watch的節(jié)點的變更信息乞娄。但是瞬逊,etcd的watch時阻塞模式的,watch某個節(jié)點后仪或,就會阻塞等待回應(yīng)确镊。
public static void etcdWatch(Watch watch, String key, Boolean usePrefix, WatchCallback callback) {
        executorService.execute(() -> {
            try {
                Watch.Watcher watcher;
                if (usePrefix) {
                    watcher = watch.watch(ByteSequence.fromString(key), WatchOption.newBuilder().withPrefix(ByteSequence.fromString(key)).build());
                } else {
                    watcher = watch.watch(ByteSequence.fromString(key));
                }
                List<WatchEvent> events = watcher.listen().getEvents();
                callback.callback(events);
            } catch (InterruptedException e) {
                logger.error(e.getMessage(), e);
            }
        });
}
  • 1.使用異步線程對key進(jìn)行watch,注意范删,我們?nèi)绻獁atch蕾域,一個服務(wù)節(jié)點下的多個實例的變更,需要在watch時指定前綴到旦,即watch當(dāng)前key為一個前綴旨巷,這樣后面的所有實例key的變化都能夠watch到廓块。
  • 2.當(dāng)watch事件觸發(fā)后,回調(diào)watchCallBack方法進(jìn)行相應(yīng)的處理契沫,這個內(nèi)容需要我們自己實現(xiàn)带猴。

etcd 獲取節(jié)點和節(jié)點內(nèi)容

  • 1.etcd為key-value形式存儲數(shù)據(jù),所以獲取key的數(shù)據(jù)非常簡單
private String getEtcdValue(String path, Boolean usePrefix) {
    try {
        KV kv = client.getKVClient();
        ByteSequence seqKey = ByteSequence.fromString(path);
        GetResponse response = kv.get(seqKey).get();
        String key = response.getKvs().get(0).getKey().toStringUtf8();
        String value = response.getKvs().get(0).getValue().toStringUtf8();
        logger.info("Get data from etcdServer, key:{}, value:{}", key, value);
        return value;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    return null;
}

Etcd Key-Value Api

鍵值A(chǔ)PI操作存儲在etcd中的鍵值對

etcd來說,鍵值對(key-value pair)是最小可操作單元,每個鍵值對都有許多字段,以protobuf格式定義懈万。

message KeyValue {
  bytes key = 1;
  int64 create_revision = 2;
  int64 mod_revision = 3;
  int64 version = 4;
  bytes value = 5;
  int64 lease = 6;
}
  • key: 以字節(jié)為單位的鍵拴清。不允許使用空密鑰。
  • value: 以字節(jié)為單位的值会通。
  • version: 版本是密鑰的版本口予。刪除將版本重置為零,任何對密鑰的修改都會增加版本號
  • Create_Revision: 修改鍵上的最后一個創(chuàng)建.
  • Mod_Revision: 修改最后修改的密鑰.
  • Lease(租約): 附在鑰匙上的租約的ID涕侈。如果租約是0沪停,則沒有租約附在鑰匙上。

除了鍵和值之外裳涛,etcd還將附加的修訂元數(shù)據(jù)作為鍵消息的一部分木张。該修訂信息按創(chuàng)建和修改的時間對鍵進(jìn)行排序,這對于管理分布式同步的并發(fā)性非常有用端三。etcd客戶端的分布式共享鎖使用創(chuàng)建修改來等待鎖定所有權(quán)舷礼。類似地,修改修訂用于檢測軟件事務(wù)內(nèi)存讀集沖突并等待領(lǐng)導(dǎo)人選舉更新郊闯。


Etcd vs Zookeeper

相較之下妻献,Zookeeper有如下缺點。

  • 1.復(fù)雜团赁。Zookeeper的部署維護(hù)復(fù)雜育拨,管理員需要掌握一系列的知識和技能;而Paxos強一致性算法也是素來以復(fù)雜難懂而聞名于世欢摄;另外熬丧,Zookeeper的使用也比較復(fù)雜,需要安裝客戶端剧浸,官方只提供了java和C兩種語言的接口锹引。
  • 2.Java編寫。這里不是對Java有偏見唆香,而是Java本身就偏向于重型應(yīng)用嫌变,它會引入大量的依賴。而運維人員則普遍希望機(jī)器集群盡可能簡單躬它,維護(hù)起來也不易出錯腾啥。
  • 3.發(fā)展緩慢。Apache基金會項目特有的“Apache Way”在開源界飽受爭議,其中一大原因就是由于基金會龐大的結(jié)構(gòu)以及松散的管理導(dǎo)致項目發(fā)展緩慢倘待。

而etcd作為一個后起之秀疮跑,其優(yōu)點也很明顯。

  • 1.簡單凸舵。使用Go語言編寫部署簡單祖娘;使用HTTP作為接口使用簡單;使用Raft算法保證強一致性讓用戶易于理解啊奄。
  • 2.數(shù)據(jù)持久化渐苏。etcd默認(rèn)數(shù)據(jù)一更新就進(jìn)行持久化。
  • 3.安全菇夸。etcd支持SSL客戶端安全認(rèn)證琼富。
    最后,etcd作為一個年輕的項目庄新,正在高速迭代和開發(fā)中鞠眉,這既是一個優(yōu)點,也是一個缺點择诈。優(yōu)點在于它的未來具有無限的可能性械蹋,缺點是版本的迭代導(dǎo)致其使用的可靠性無法保證,無法得到大項目長時間使用的檢驗吭从。然而朝蜘,目前CoreOS、Kubernetes和Cloudfoundry等知名項目均在生產(chǎn)環(huán)境中使用了etcd涩金,所以總的來說,etcd值得你去嘗試暇仲。

etcd 基本操作

docker-compose形式啟動etcd單節(jié)點服務(wù)

etcd:
    container_name: etcd
    # image: quay.io/coreos/etcd:v3.1
    image: registry.cn-hangzhou.aliyuncs.com/coreos_etcd/etcd:v3
    ports:
      - "2379:2379"
      - "4001:4001"
      - "2380:2380"
    environment:
      - ETCDCTL_API=3
      - TZ=CST-8
      - LANG=zh_CN.UTF-8
    command: 
      /usr/local/bin/etcd
      -name node1 
      -data-dir /etcd-data
      -advertise-client-urls http://${host_ip}:2379,http://${host_ip}:4001
      -listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001
      -initial-advertise-peer-urls http://${host_ip}:2380
      -listen-peer-urls http://0.0.0.0:2380
      -initial-cluster-token docker-etcd 
      -initial-cluster node1=http://${host_ip}:2380
      -initial-cluster-state new 
    volumes:
      - "/data/config/etcd/ca-certificates/:/etc/ssl/certs"
      - "/data/conf/etcd/data:/etcd-data"

etcd v3 基本api

  • 1.進(jìn)入容器
docker exec -it etcd sh
  • 2.設(shè)置鍵步做、修改鍵
etcdctl put /maple value
  • 3.刪除鍵
etcdctl del /maple
  • 4.刪除所有/test前綴的節(jié)點
etcdctl del  /test --prefix
  • 5.查詢Key
etcdctl get /test/ok
  • 6.前綴查詢
etcdctl get /test/ok --prefix
  • 7.watch key
etcdctl watch /maple/services
  • 8.watch子節(jié)點
etcdctl watch /maple/services --prefix
  • 9.申請租約、授權(quán)租約

申請租約

etcdctl lease grant 40
    result: lease 4e5e5b853f528859 granted with TTL(40s)

授權(quán)租約

etcdctl put --lease=4e5e5b853f528859 /maple/s 123

撤銷

etcdctl lease revoke 4e5e5b853f5286cc

租約續(xù)約

etcdctl lease keep-alive 4e5e5b853f52892b
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奈附,一起剝皮案震驚了整個濱河市全度,隨后出現(xiàn)的幾起案子筐带,更是在濱河造成了極大的恐慌行楞,老刑警劉巖敦姻,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钧栖,死亡現(xiàn)場離奇詭異洛二,居然都是意外死亡奸绷,警方通過查閱死者的電腦和手機(jī)锁施,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進(jìn)店門墩剖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挑胸,“玉大人痒筒,你說我怎么就攤上這事。” “怎么了簿透?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵移袍,是天一觀的道長。 經(jīng)常有香客問我老充,道長葡盗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任啡浊,我火速辦了婚禮觅够,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虫啥。我一直安慰自己蔚约,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布涂籽。 她就那樣靜靜地躺著苹祟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪评雌。 梳的紋絲不亂的頭發(fā)上树枫,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機(jī)與錄音景东,去河邊找鬼砂轻。 笑死,一個胖子當(dāng)著我的面吹牛斤吐,可吹牛的內(nèi)容都是我干的搔涝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼和措,長吁一口氣:“原來是場噩夢啊……” “哼庄呈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起派阱,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诬留,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后贫母,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體文兑,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年腺劣,在試婚紗的時候發(fā)現(xiàn)自己被綠了绿贞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡誓酒,死狀恐怖樟蠕,靈堂內(nèi)的尸體忽然破棺而出贮聂,到底是詐尸還是另有隱情,我是刑警寧澤寨辩,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布吓懈,位于F島的核電站,受9級特大地震影響靡狞,放射性物質(zhì)發(fā)生泄漏耻警。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一甸怕、第九天 我趴在偏房一處隱蔽的房頂上張望甘穿。 院中可真熱鬧,春花似錦梢杭、人聲如沸温兼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽募判。三九已至,卻和暖如春咒唆,著一層夾襖步出監(jiān)牢的瞬間届垫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工全释, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留装处,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓浸船,卻偏偏與公主長得像妄迁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子李命,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 因為工作需求判族,公司需要使用ETCD來做gRPC服務(wù)的負(fù)載均衡,以及集群管理项戴,所以對etcd做了一些研究,希望能給大...
    Jay_Guo閱讀 46,576評論 8 47
  • from http://www.infoq.com/cn/articles/etcd-interpretation...
    小樹苗苗閱讀 13,940評論 3 38
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理槽惫,服務(wù)發(fā)現(xiàn)周叮,斷路器,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 小時候歷史就是一個故事界斜。 孩子在父母講述的歷史故事中聽見英雄的事跡仿耽,正義的化身,讓孩子覺得歷史很有趣各薇。 長大了歷史...
    小泥孩黑山站閱讀 189評論 0 0
  • 帝都的雨季開始了项贺,一大早出門在小區(qū)里七拐八拐還是鞋濕透了君躺。據(jù)說很多地方都淹了,不禁感恩自己的生存環(huán)境還是很棒的开缎。 ...
    小王子的前世今生閱讀 189評論 0 0