使用C# 和Consul進行分佈式系統協調

隨着大數據時代的到來,分佈式是解決大數據問題的一個主要手段,隨着愈來愈多的分佈式的服務,如何在分佈式的系統中對這些服務作協調變成了一個很棘手的問題。今天咱們就來看看如何使用C# ,利用開源對分佈式服務作協調。html

在對分佈式的應用作協調的時候,主要會碰到如下的應用場景:node

  • 業務發現(service discovery)

找到分佈式系統中存在那些可用的服務和節點linux

  • 名字服務 (name service)

經過給定的名字知道到對應的資源git

  • 配置管理 (configuration management)

如何在分佈式的節點中共享配置文件,保證一致性。github

  • 故障發現和故障轉移 (failure detection and failover)

當某一個節點出故障的時候,如何檢測到並通知其它節點, 或者把想用的服務轉移到其它的可用節點web

  • 領導選舉(leader election)

如何在衆多的節點中選舉一個領導者,來協調全部的節點json

  • 分佈式的鎖 (distributed exclusive lock)

如何經過鎖在分佈式的服務中進行同步bootstrap

  • 消息和通知服務 (message queue and notification)

如何在分佈式的服務中傳遞消息,以通知的形式對事件做出主動的響應windows

Consul 瀏覽器

Consul是用Go開發的分佈式服務協調管理的工具,它提供了服務發現,健康檢查,Key/Value存儲等功能,而且支持跨數據中心的功能。consul提供的一些關鍵特性:

  • service discovery:consul經過DNS或者HTTP接口使服務註冊和服務發現變的很容易,一些外部服務,例如saas提供的也能夠同樣註冊。
  • health checking:健康檢測使consul能夠快速的告警在集羣中的操做。和服務發現的集成,能夠防止服務轉發到故障的服務上面。
  • key/value storage:一個用來存儲動態配置的系統。提供簡單的HTTP接口,能夠在任何地方操做。
  • multi-datacenter:無需複雜的配置,便可支持任意數量的區域。

Consul基於HTTP的API能夠方便的和各類語言進行綁定,C# 語言綁定https://github.com/PlayFab/consuldotnet

Consul在Cluster上的每個節點都運行一個Agent,這個Agent可使用Server或者Client模式。Client負責到Server的高效通訊,相對爲無狀態的。 Server負責包括選舉領導節點,維護cluster的狀態,對全部的查詢作出響應,跨數據中心的通訊等等。

consul官網已經有編譯好的二進制包,支持各類平臺:win、linux等等,下載符合你平臺的軟件包:在這裏,下載包:0.5.2_windows_386.zip。解壓完畢後只有一個consul文件。

D:\GitHub\consuldotnet\Consul.Test>consul

usage: consul [--version] [--help] <command> [<args>]

Available commands are:

agent Runs a Consul agent

configtest Validate config file

event Fire a new event

exec Executes a command on Consul nodes

force-leave Forces a member of the cluster to enter the "left" state

info Provides debugging information for operators

join Tell Consul agent to join cluster

keygen Generates a new encryption key

keyring Manages gossip layer encryption keys

leave Gracefully leaves the Consul cluster and shuts down

lock Execute a command holding a lock

maint Controls node or service maintenance mode

members Lists the members of a Consul cluster

monitor Stream logs from a Consul agent

reload Triggers the agent to reload configuration files

version Prints the Consul version

watch Watch for changes in Consul

consul安裝完畢後,agent就能夠啓動了,agent能夠運行在server或者client模式,每一個數據中心至少有一個agent運行在server模式,通常建議是3或者5個server。部署單個server是很是很差的,由於在失敗場景中出現數據丟失是不可避免的。本文涵蓋的是建立一個新的數據中心,全部其餘的agents都運行在client模式,這是一個很是輕量級的服務註冊進程,它會運行健康監測,並將查詢結果轉發到服務。agent必須運行在集羣中的每個節點上。

consul.exe agent -config-file test_config.json

咱們先運行一個agent在server模式:

D:\GitHub\consuldotnet\Consul.Test> consul.exe agent -config-file test_config.json

==> WARNING: Bootstrap mode enabled! Do not enable unless necessary

==> WARNING: Windows is not recommended as a Consul server. Do not use in production.

==> WARNING: It is highly recommended to set GOMAXPROCS higher than 1

==> Starting Consul agent...

==> Starting Consul agent RPC...

==> Consul agent running!

Node name: 'GEFFZHANG-NB'

Datacenter: 'dc1'

Server: true (bootstrap: true)

Client Addr: 127.0.0.1 (HTTP: 8500, HTTPS: -1, DNS: 8600, RPC: 8400)

Cluster Addr: 192.168.1.4 (LAN: 8301, WAN: 8302)

Gossip encrypt: false, RPC-TLS: false, TLS-Incoming: false

Atlas: <disabled>

 

==> Log data will now stream in as it occurs:

 

2015/08/09 09:14:48 [INFO] serf: EventMemberJoin: GEFFZHANG-NB 192.168.1.4

2015/08/09 09:14:48 [INFO] serf: EventMemberJoin: GEFFZHANG-NB.dc1 192.168.1.4

2015/08/09 09:14:48 [INFO] raft: Node at 192.168.1.4:8300 [Follower] entering Follower state

2015/08/09 09:14:48 [INFO] consul: adding server GEFFZHANG-NB (Addr: 192.168.1.4:8300) (DC: dc1)

2015/08/09 09:14:48 [INFO] consul: adding server GEFFZHANG-NB.dc1 (Addr: 192.168.1.4:8300) (DC: dc1)

2015/08/09 09:14:48 [ERR] agent: failed to sync remote state: No cluster leader

2015/08/09 09:14:50 [WARN] raft: Heartbeat timeout reached, starting election

2015/08/09 09:14:50 [INFO] raft: Node at 192.168.1.4:8300 [Candidate] entering Candidate state

2015/08/09 09:14:50 [DEBUG] raft: Votes needed: 1

2015/08/09 09:14:50 [DEBUG] raft: Vote granted. Tally: 1

2015/08/09 09:14:50 [INFO] raft: Election won. Tally: 1

2015/08/09 09:14:50 [INFO] raft: Node at 192.168.1.4:8300 [Leader] entering Leader state

2015/08/09 09:14:50 [INFO] consul: cluster leadership acquired

2015/08/09 09:14:50 [INFO] consul: New leader elected: GEFFZHANG-NB

2015/08/09 09:14:50 [INFO] raft: Disabling EnableSingleNode (bootstrap)

2015/08/09 09:14:50 [DEBUG] raft: Node 192.168.1.4:8300 updated peer set (2): [192.168.1.4:8300]

2015/08/09 09:14:50 [DEBUG] consul: reset tombstone GC to index 2

2015/08/09 09:14:50 [INFO] consul: member 'GEFFZHANG-NB' joined, marking health alive

2015/08/09 09:14:51 [INFO] agent: Synced service 'consul'

2015/08/09 09:16:03 [DEBUG] agent: Service 'consul' in sync

2015/08/09 09:17:30 [DEBUG] agent: Service 'consul' in sync

2015/08/09 09:18:38 [DEBUG] agent: Service 'consul' in sync

2015/08/09 09:19:47 [DEBUG] http: Request /v1/status/peers (0)

2015/08/09 09:19:52 [DEBUG] agent: Service 'consul' in sync

正如你看到的同樣,consul agent已經啓動了,而且打印了一些日誌到終端上,從日誌中能夠看到咱們的agent已經運行在server模式了,而且已是整個集羣的領導節點。並且,本地成員已經被標記爲集羣中的健康成員了。這時候你在另外一個終端中運行consul members就能夠看到整個集羣中的成員了。這時候你只能看到你本身,由於咱們的集羣中還沒加入其餘成員。

輸出已經顯示了你本身的節點信息,有地址信息、健康情況、在集羣中的角色、以及一些版本信息,若是要查看一些metadata,則能夠加入-detailed標記

consul members命令輸出的信息是基於gossip協議產生的,而且最終一致的。

 

KV基本操做

Consul提供了一個簡單的K/V存儲系統,這能夠用來動態獲取配置、進行服務協調、主節點選舉,其餘開發人員能想到的build過程等等。

var client = new Client();

var kv = client.KV;

var key = GenerateTestKeyName();

var value = Encoding.UTF8.GetBytes("test");

var getRequest = kv.Get(key);

Assert.IsNull(getRequest.Response);

var pair = new KVPair(key)

{

Flags = 42,

Value = value

};

var putRequest = kv.Put(pair);

Assert.IsTrue(putRequest.Response);

getRequest = kv.Get(key);

var res = getRequest.Response;

Assert.IsNotNull(res);

Assert.IsTrue(StructuralComparisons.StructuralEqualityComparer.Equals(value, res.Value));

Assert.AreEqual(pair.Flags, res.Flags);

Assert.IsTrue(getRequest.LastIndex > 0);

var del = kv.Delete(key);

Assert.IsTrue(del.Response);

getRequest = kv.Get(key);

Assert.IsNull(getRequest.Response);

服務發現(Service Discovery)和健康檢查(Health Check)

Consul的另外一個主要的功能是用於對分佈式的服務作管理,用戶能夠註冊一個服務,同時還提供對服務作健康檢測的功能。

服務定義:一個服務能夠經過提供服務定義配置文件或者經過調用HTTP API來動態的增長、刪除、修改服務。

服務查詢:一旦agent啓動後,而且服務已經同步,咱們就可使用DNS或者HTTP API來進行查詢了。

服務升級:服務定義的升級能夠經過先修改服務定義配置文件,而後給agent發送一個SIGHUP信號便可,這樣容許你在升級服務時,而不會產生agent宕機時間或者服務不可達。或者經過HTTP API接口來動態的增長、刪除、修改服務。

Consul支持三種Check的模式:

  • 調用一個外部腳本(Script),在該模式下,consul定時會調用一個外部腳本,經過腳本的返回內容得到對應服務的健康狀態。
  • 調用HTTP,在該模式下,consul定時會調用一個HTTP請求,返回2XX,則爲健康;429 (Too many request)是警告。其它均爲不健康
  • 主動上報,在該模式下,服務須要主動調用一個consul提供的HTTP PUT請求,上報健康狀態。

C# API提供對應的接口

  • Client.Agent.Service
  • Client.Agent.Check

Consul的Health Check,經過調用腳本,HTTP或者主動上報的方式檢查服務的狀態,更爲靈活,能夠得到等多的信息,可是也須要作更多的工做。

故障檢測(Failure Detection)

Consul提供Session的概念,利用Session能夠檢查服務是否存活。對每個服務咱們均可以建立一個session對象,注意這裏咱們設置了ttl,consul會以ttl的數值爲間隔時間,持續的對session的存活作檢查。對應的在服務中,咱們須要持續的renew session,保證session是合法的。

var client = new Client();

var sessionRequest = client.Session.Create(new SessionEntry() { TTL = TimeSpan.FromSeconds(10) });

var id = sessionRequest.Response;

Assert.IsTrue(sessionRequest.RequestTime.TotalMilliseconds > 0);

Assert.IsFalse(string.IsNullOrEmpty(sessionRequest.Response));

var tokenSource = new CancellationTokenSource();

var ct = tokenSource.Token;

client.Session.RenewPeriodic(TimeSpan.FromSeconds(1), id, WriteOptions.Empty, ct);

tokenSource.CancelAfter(3000);

Task.Delay(3000, ct).Wait(ct);

var infoRequest = client.Session.Info(id);

Assert.IsTrue(infoRequest.LastIndex > 0);

Assert.IsNotNull(infoRequest.KnownLeader);

Assert.AreEqual(id, infoRequest.Response.ID);

Assert.IsTrue(client.Session.Destroy(id).Response);

這裏注意,由於是基於ttl(最小10秒)的檢測,從業務中斷到被檢測到,至少有10秒的時延,對應須要實時響應的情景,並不適用。

領導選舉和分佈式的鎖

這篇文檔介紹瞭如何利用Consul的KV存儲來實現Leader Election,利用Consul的KV功能,能夠很方便的實現領導選舉和鎖的功能。

WEB UI

consul一樣也支持web界面,這個UI能夠用來查看全部的服務和節點,全部的健康檢測和它們當前的狀態,讀取設置K/V系統的值。UI默認自動支持多datacenter。這些UI是靜態html你不須要單獨運行一個web服務器,consul agent自己能夠配置一個web服務。

下載UI組件:WEB UI

        下載完成後是一個0.5.2_web_ui.zip壓縮文件,解壓後是一個dist目錄。而後添加-ui-dir參數和-client參數從新啓動agent。

D:\GitHub\consuldotnet\Consul.Test> consul.exe agent -config-file test_config.json -ui-dir=D:\GitHub\consuldotnet\Consul.Test\0.5.2_web_ui\dist

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

有services、nodes、K/V、acl、datacenter的管理,很完善的一個系統了。

總結

Consul做爲使用Go語言開發的分佈式協調,對業務發現的管理提供很好的支持,他的HTTP API也能很好的和不一樣的語言綁定,並支持跨數據中心的應用。缺點是相對較新,適合喜歡嘗試新事物的用戶。

https://github.com/anurse/Consulate

https://github.com/geffzhang/Consul-IO-WindowsDemo

https://github.com/catwithboots/Hortlak

https://github.com/catwithboots/Orek

https://github.com/geffzhang/Pk.OrleansUtils

http://blog.csdn.net/u010246789/article/category/6286612 

相關文章
相關標籤/搜索