1. 程式人生 > >服務發現系統consul介紹

服務發現系統consul介紹

最近在折騰服務發現這個功能,偶然發現了consul,發現國內資料很少(包括etcd),看了官方文件後,發現很厲害啊,consul是一個用來配置服務發現的工具,consul是分散式的、高可用、橫向擴充套件的。consul提供的一些關鍵特性:

service discovery:consul通過DNS或者HTTP介面使服務註冊和服務發現變的很容易,一些外部服務,例如saas提供的也可以一樣註冊。

health checking:健康檢測使consul可以快速的告警在叢集中的操作。和服務發現的整合,可以防止服務轉發到故障的服務上面。

key/value storage:一個用來儲存動態配置的系統。提供簡單的HTTP介面,可以在任何地方操作。

multi-datacenter:無需複雜的配置,即可支援任意數量的區域。

下面初步的講解一下consul的特性: 

1    install consul

        我的機器是ubuntu14.04系統, 先下載consul軟體包,consul官網已經有編譯好的二進位制包,支援各種平臺:win、linux等等,下載符合你平臺的軟體包: 在這裡 , 下載包: 0.4.1_linux_amd64.zip。解壓完畢後只有一個consul檔案。

2    run agent

consul安裝完畢後,agent就可以啟動了,agent可以執行在server或者client模式,每個資料中心至少有一個agent執行在server模式,一般建議是3或者5個server。部署單個server是非常不好的,因為在失敗場景中出現數據丟失是不可避免的。本文涵蓋的是建立一個新的資料中心,所有其他的agents都執行在client模式,這是一個非常輕量級的服務註冊程序,它會執行健康監測,並將查詢結果轉發到服務。agent必須執行在叢集中的每一個節點上。 

我們先執行一個agent在server模式: 

./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul

正如你看到的一樣,consul agent已經啟動了,並且列印了一些日誌到終端上,從日誌中可以看到我們的agent已經執行在server模式了,並且已經是整個叢集的領導節點。而且,本地成員已經被標記為叢集中的健康成員了。這時候你在另一個終端中執行consul members就可以看到整個叢集中的成員了。這時候你只能看到你自己,因為我們的叢集中還沒加入其他成員。 

輸出已經顯示了你自己的節點資訊,有地址資訊、健康狀況、在叢集中的角色、以及一些版本資訊,如果要檢視一些metadata,則可以加入-detailed標記 

consul members命令輸出的資訊是基於gossip協議產生的,並且最終一致的。也可以使用HTTP API來檢視整個叢集的強一致性檢視資訊。 

除了使用HTTP API介面可以檢視叢集的檢視資訊外,也可以使用DNS介面來檢視,要在你的節點名稱後面加上node.consul字串。 

    停止agent服務,在第一個終端中,你可以使用ctrl-c來優雅的停止agent,如果你停止的是client,當你優雅的離開後,consul會通知叢集中的其他成員你這個節點以及處於left狀態。如果你是強制killed掉agent,叢集中的其他成員會認為你是failed了。當成員leaves後,該成員的services和checks會從catalog被移除,當成員fails後,該成員的健康狀態會被簡單的標記為critical,但是不會從catalog刪除。consul會自動的嘗試連結failed的節點,這樣允許節點在某些網路狀況中恢復,如果節點是left狀態,則不會再聯絡該節點。

3    service

前面兩節我們啟動了第一個agent,並查看了叢集中的成員,利用HTTP API查詢了一些節點資訊,在這一節,我們會註冊我們的第一個服務,並查詢該服務。 

服務定義:一個服務可以通過提供 服務定義配置檔案 或者通過呼叫 HTTP API 來註冊。我們先通過配置服務定義配置檔案來註冊新服務,這是最普通的服務註冊方法,首先為consul建立一個配置檔案目錄,按照linux的風格,一般建立在/etc/consul.d目錄下,consul會載入在該目錄下的所有檔案(以json結尾),接著我們定義一個服務定義配置檔案,我們這個要註冊的服務是提供web服務的,執行在80埠,會給該服務打一些tag,因此這個配置檔案就命名為web.json。配置完成後,我們再次重新啟動agent,並在命令列提供配置檔案目錄。 

mkdir /etc/consul.d
echo '{"service": {"name": "web", "tags": ["rails"], "port": 80}}' >/etc/consul.d/web.json
./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -config-dir /etc/consul.d

 

你會注意到輸出的日誌中,最後有一行顯示已經synced service web了,這表示已經從配置檔案中載入了相關資訊。如果你想註冊多個服務,則可以建立多個配置檔案。 

服務查詢:一旦agent啟動後,並且服務已經同步,我們就可以使用DNS或者HTTP API來進行查詢了。我們首先使用DNS來查詢,在使用DNS查詢時,services的名稱是name.service.consul,所有的DNS names都在consul空間下面(consul空間是可以修改的),service關鍵字是告訴consul我們在查詢services,name則是service的名稱,我們的web服務註冊後,我們則可以使用下面的名稱進行查詢:web.service.consul 

你可以看到一個A記錄,記錄了服務可達的ip地址,A記錄只能顯示ip地址,你也可以使用DNS API來檢索ip/port,只需要新增SRV記錄即可: 

SRV記錄的返回結果說明web服務執行在Docker-3.node.dc1.consul節點的80埠上面,另外,我們也可是使用DNS API過濾出只符合tag標記的sevice,可以在dns查詢時使用如下格式:tag.name.service.consul,tag則是你想過濾的tag。

下面我們使用HTTP API介面來查詢一下服務: 

curl -s http://localhost:8500/v1/catalog/service/web | python -m json.tool

 

服務升級:服務定義的升級可以通過先修改服務定義配置檔案,然後給agent傳送一個SIGHUP訊號即可,這樣允許你在升級服務時,而不會產生agent宕機時間或者服務不可達。或者通過HTTP API介面來動態的增加、刪除、修改服務。 

4    consul cluster

現在我們已經啟動了第一個agent,註冊了第一個服務,並用API介面做了一些查詢,這已經顯示了consul的易用性,但是我們還不知道要怎麼橫向擴充套件consul,在這一節我們建立一個多成員的叢集。當你啟動一個consul agent的時候,agent一開始並不知道其他節點,agent是叢集中一個孤立的點,為了知道叢集中的其他成員,agent必須加入一個叢集中,加入一個集群后,agent會很快知道該叢集中的其他成員,一個agent可以加入其他agent,它也不必執行在server模式。為了模擬真實的叢集,我使用三臺ubuntu14.04構建一個consul叢集,機器資訊如下: 

192.168.1.100  Docker-1  server
192.168.1.101  Docker-2  client
192.168.1.102  Docker-3  client

我門先在第一臺機器上啟動agent,以server模式執行,並且指定一個node名稱,一般以主機名為node名稱,這個名稱要唯一。我們同時提供要監聽的地址,server的這個地址對於叢集中的其他agent必須是可達的,下面我們啟動: 

./consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=Docker-1 -bind=192.168.1.100

在100上的server模式的agent啟動後,我們來到101上啟動我們的第二個agent,這個agent繫結101節點的ip地址。下面我們啟動101上的節點, 

./consul agent -data-dir /tmp/consul -node=Docker-2 -bind=192.168.1.101

 

101上的節點啟動後,可以看到101在報錯,之前說過一個叢集中至少要有一個server agent,101啟動的時候沒有設定server模式,這時候就相當於101在它自己的叢集中,但是該叢集中沒有server,只有一個client,我們有兩個agent在執行,一個server模式,一個client模式,但是這兩個節點彼此都互不知道,它們都執行在自己的叢集中,你可以通過consul members來檢視,我們下面就要把101的client加入到server的叢集中。 在100的server上面,通知101的agent加入server叢集。 這時候應該在agent的輸出log上看到一些資訊,這時候再執行consul members就會看到整個叢集的成員了。 

先看101的agent增加了哪些日誌 

可以看到該agent加入Docker-1的叢集中了,Docker-1是叢集的leader,再看看Docker-1的agent有哪些日誌輸出 

agent Docker-2加入進來了,並標記Docker-2的狀態為alive。 

有個快捷的方法,在agent啟動時就可以直接加入叢集,在consul agent啟動的時候使用-join引數,即可把agent加入叢集中,我們就用這個方法把Docker-3直接加入Docker-1的叢集中。 

./consul agent -data-dir /tmp/consul -node=Docker-3 -join=192.168.1.100 -bind=192.168.1.102

再來看看叢集中的成員,已經加入了Docker-3 

而且叢集中的成員都收到了Docker-3加入的資訊,我們看看DOcker-2的agent打印出的log資訊 

節點查詢,就像service查詢一樣,consul也提供DNS和HTTP API介面來查詢節點,對於DNS查詢,你可以使用name.node.consul或者name.datacenter.node.consul來查詢,如果datacenter被省略,則預設查詢本地datacenter。 

離開叢集,就像前面的方法一樣,使用ctrl-c來離開叢集,或者強制killed掉agent,當然這兩種方法的優劣前面已經講過了。 

5    health check

現在我們已經知道怎麼執行consul、增加節點和服務、查詢節點和服務、以及建立叢集,這一節我們增加節點和服務間的健康監測,這是服務發現的重要組成部分,因為它要阻止訪問不健康的服務。 

檢測定義:就像服務定義一樣,我們可以通過 檢測定義配置檔案 或者 HTTP API 介面來定義檢測。我們定義檢測配置就像配置服務定義一樣,我們在Docker-2節點的consul配置目錄增加兩個配置檔案,一個配置檔案是host層面的檢測,一個是server層面的檢測。 

host檢測,每30s檢測一次 

echo '{"check": {"name": "ping", "script": "ping -c1 www.baidu.com >/dev/null", "interval": "30s"}}' >/etc/consul.d/ping.json

server檢測,每10秒中檢測一次。已經在Docker-2啟動了apache服務 

echo '{"service": {"name": "web", "tags": ["rails"], "port": 80,
  "check": {"script": "curl localhost:80 >/dev/null 2>&1", "interval": "10s"}}}' >/etc/consul.d/web.json

然後重啟agent或者給當前的agent程序傳送一個SIGHUP訊號(kill -s SIGHUP agent_pid),因為我們在啟動agent的時候並沒有新增-config-dir標記,所以agent並不知道consul的配置檔案目錄在哪裡,所以我們要ctrl-c來重啟agent,並新增配置檔案目錄 

./consul agent -data-dir /tmp/consul -join=Docker-1 -node=Docker-2 -bind=192.168.1.101 -config-dir=/etc/consul.d

檢查健康狀態,我們已經添加了一些健康檢測的機制,現在我們可以使用HTTP API來檢測了,我們先檢視所有的檢測。 

curl -s http://localhost:8500/v1/health/state/any | python -m json.tool

也可以使用DNS介面來查詢。 

6    K/V data

上面章節我們已經實現了服務發現和健康檢測,consul也提供了一個簡單的K/V儲存系統,這可以用來動態獲取配置、進行服務協調、主節點選舉,其他開發人員能想到的build過程等等。 

為了演示怎麼操作K/V系統,我們將會操作少量資料。我們在Docker-2節點上進行測試,首先要檢測K/V系統中是否已經有key存在。 

curl -v http://127.0.0.1:8500/v1/kv/?recurse

可以看到目前K/V系統中並沒有key,我們http返回的是404狀態碼,現在我們put一些資料進去: 

curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/web/key1
curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/web/key2?flags=42
curl -X PUT -d 'test' http://127.0.0.1:8500/v1/kv/web/web/sub/key3

開始檢視K/V系統中的key

curl -s http://127.0.0.1:8500/v1/kv/?recurse|python -m json.tool

我們建立了三個key,每個key的value都是test,在K/V系統中值都是base64加密過的,我們給'web/key2'這個key添加了一個tag,所有的key支援64bit的整形長度,在插入完畢後,可以用?recurse來檢視所有的key,你也可以只檢視單個key 

curl -s http://127.0.0.1:8500/v1/kv/web/key1|python -m json.tool

刪除key也是很容易的,我們可以指定全路徑來刪除單個key,也可以使用?recurse來刪除所有key。 

curl -s http://127.0.0.1:8500/v1/kv/web/key1|python -m json.tool

可以通過給一個key賦予新值來進行update,另外,consul會執行一個Check-And-Set的操作,確保更新操作的原子性。這可以通過提供?cas=引數來實現,cas的值是ModifyIndex的值。 

curl -X PUT -d 'newval' http://127.0.0.1:8500/v1/kv/web/key1?cas=106
curl -X PUT -d 'newval' http://127.0.0.1:8500/v1/kv/web/key1?cas=106
curl -s http://127.0.0.1:8500/v1/kv/web/key1|python -m json.tool

在上面的情況可以看到,第一次CAS update成功了,因為上一次修改的時間是106,但是第二次CAS的操作失敗了,因為ModifyIndex的大小小於106,。

7    WEB UI

consul同樣也支援web介面,這個ui可以用來檢視所有的服務和節點,所有的健康檢測和它們當前的狀態,讀取設定K/V系統的值。ui預設自動支援多datacenter。這些ui是靜態html和jsp檔案,你不需要單獨執行一個web伺服器,consul agent本身可以配置一個web服務。我們在Docker-3上配置該UI服務。 

下載UI元件: WEB UI 

下載完成後是一個0.4.1_web_ui.zip壓縮檔案,解壓後是一個dist目錄。先ctrl-c掉Docker-3上的agent,然後新增-ui-dir引數和-client引數重新啟動agent。 

./consul agent -data-dir /tmp/consul -node=Docker-3 -join=192.168.1.100 -bind=192.168.1.102 -ui-dir=/opt/dist -client=192.168.1.102

在瀏覽器中輸入http://192.168.1.102:8500,即可訪問UI了 

        看著很不錯,有services、nodes、K/V、acl、 datacenter的管理,看起來比etcd好一些。