使用etcd watch做服務發現


開發的進度已經到了服務發現了,在選擇zookeeper和etcd的時候,我還真猶豫了,雖然兩個都曾用過,但是長久不用就都忘了,又查了下兩者的對比資料,發現在服務發現方面,兩者都差不多的。只是zookeeper有Ephemeral的概念,Ephemeral結點在Zookeeper中是一個臨時結點,這些結點只要創建它的結點session不掛,它就一直存在,當session中止了,比如客戶端進程掛掉了,那么在zookeeper的結點也就被刪除了。 etcd不支持ZooKeeper的ephemeral臨時節點的概念,要監控服務的狀態似乎比較麻煩。 哥還在github etcd issue里,問了那個xiang90 (中國人)….

好了,不能只看別人zookeeper vs etcd的評價,人雲亦雲不是我的風格,昨天花了點時間把監控的服務發現功能在zookeeper和etcd都測試了下,結果他們都適合服務注冊發現….  雖然zookeeper公司有專門的集群,但是真是不想接入他們….   怎么簡單怎么來,那就用etcd吧,etcd的設計理念跟運維都是比較簡單的。

 

下面是我以前做測試的效果圖,為了避嫌,我把圖表的數據都裁剪了下,反正看明白他的意思就行了,綠色代碼OK,紅色代表問題。 

 

關於模塊的服務注冊我是這么設計的 ~

/buzz/buzzadmin/download

/buzz/buzzadmin/api

buzz是大項目,buzzadmin是子項目,api 跟 download都是子項目中的兩個模塊。 這樣就有了層級的關系。 /A/B/C  ,B死了,C也就無意義了。 A死了,B也就完了,下層受限於上層。

etcd和zookeeper kv的存儲本來就是這種樹形目錄,很適合我上面的監控需求設計。 

我這里放兩個python操作etcd服務的小例子。

 

set client:  (這個寫入的客戶端)

import etcd
client = etcd.Client()
c = 0
for i in range(100):
   client.write('/nodes/n%s'%i, 1,ttl=10)
   c += 1
   print i
 

watch client: (這個是監控端)

import etcd
client = etcd.Client()

c = 0 
while 1:
    print client.watch('/nodes/',recursive=True)
    c += 1    
    print c

這樣會造成什么問題?  我想大家在看我watch client代碼的時候,估計發現了問題所在。 

寫入端比如進行了100個set操作,以為他有ttl的配置,所以當他expire過期的時候,我的watch也是會收到請求的。 我一開始沒有找到etcd watch有那樣駐守監控的函數,所以就用以前監控socket recv那樣,使用while循環地調用clent.watch() 。  這樣造成的問題是,我這邊收到節點反饋后,再去注冊監聽,這時候會丟失很多etcd反饋的信息的。   再來看看他丟失了多少,寫入段100個set,還有100個expire的action。watch理應說到200個操作,結果只有150個,也就是丟失了50個。

找了下資料,看到一老外在stackoverflow.com 上說,他也是用while,一剎那間,眼前漂出一行字,caonima…..

最后直接看python-etcd的代碼,原以為他會寫的復雜,結果這代碼只是http api的封裝罷了。  下面代碼是python-etcd里面關於watch監控的描述。注意有個eternal_watch,只是看字面的一面就知道他是我們要找尋找的,他構造了Generator生成器,然后用yield關鍵字返回。

另外watch函數其實就是self.read(self,wait=True)

def eternal_watch(self, key, index=None, recursive=None):
    """
    Generator that will yield changes from a key.
    Note that this method will block forever until an event is generated.
    Args:
        key (str):  Key to subcribe to.
        index (int):  Index from where the changes will be received.
    Yields:
        client.EtcdResult
    """
    local_index = index
    while True:
        response = self.watch(key, index=local_index, timeout=0, recursive=recursive)
        local_index = response.modifiedIndex + 1
        yield response


def watch(self, key, index=None, timeout=None, recursive=None):

    _log.debug("About to wait on key %s, index %s", key, index)
    if index:
        return self.read(key, wait=True, waitIndex=index, timeout=timeout,
                         recursive=recursive)
    else:
        return self.read(key, wait=True, timeout=timeout,
                         recursive=recursive)


def read(self, key, **kwdargs):

    _log.debug("Issuing read for key %s with args %s", key, kwdargs)
    key = self._sanitize_key(key)

    params = {}
    for (k, v) in kwdargs.items():
        if k in self._read_options:
            if type(v) == bool:
                params[k] = v and "true" or "false"
            elif v is not None:
                params[k] = v

    timeout = kwdargs.get('timeout', None)

    response = self.api_execute(
        self.key_endpoint + key, self._MGET, params=params,
        timeout=timeout)
    return self._result_from_response(response)

另外說下通過第一層key,取出所有下層key的方法…

directory = client.get("/nodes")

#可以取出所有
for result in directory.children:
  print(result.key + ": " + result.value)

#只能取出第一個
print(directory.children.next().value)

到此,我要講述的坑就扯完成了….   etcd是個好東西,夠簡單,以前做配置集中管理的時候有用過etcd,雖然后期替換成zookeeper了。另外我沒在線上用過etcd集群,但在社區中看到不少人在用,反饋也不錯。  總之,etcd值得一用….. 

另外這里記錄etcd的安裝方法,環境是linux,以前記錄的文檔沒了,就貼在這里吧。 

curl -L  https://github.com/coreos/etcd/releases/download/v2.1.3/etcd-v2.1.3-linux-amd64.tar.gz -o etcd-v2.1.3-linux-amd64.tar.gz
tar xzvf etcd-v2.1.3-linux-amd64.tar.gz
cd etcd-v2.1.3-linux-amd64
./etcd

或者是直接用docker啟動

docker run -p 2379:2379 -v /usr/share/ca-certificates/:/etc/ssl/certs quay.io/coreos/etcd:v2.1.3

另外需要注意的是,docker默認啟動是綁定在本地的4001端口,如果想綁定所有的網卡上,也就是0.0.0.0 ,可以./etcd -addr 0.0.0.0:4001

etcd解壓的時候,貌似沒有默認的配置文件,有興趣的朋友可以用我的etcd 配置文件。

addr = "127.0.0.1:4001"
bind_addr = "127.0.0.1:4001"
ca_file = ""
cert_file = ""
cors = []
cpu_profile_file = ""
data_dir = "/var/xiaorui.cc/data/"
discovery = "http://etcd.local:4001/v2/keys/_etcd/registry/examplecluster"
http_read_timeout = 10.0
http_write_timeout = 10.0
key_file = ""
peers = []
peers_file = ""
max_result_buffer = 1024
max_retry_attempts = 3
name = "default-name"
snapshot = true
verbose = false
very_verbose = false

[peer]
addr = "127.0.0.1:7001"
bind_addr = "127.0.0.1:7001"
ca_file = ""
cert_file = ""
key_file = ""

[cluster]
active_size = 9
remove_delay = 1800.0
sync_interval = 5.0

大家覺得文章對你有些作用! 如果想賞錢,可以用微信掃描下面的二維碼,感謝!
另外再次標注博客原地址   xiaorui.cc

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM