隨着大數據時代的到來,分佈式是解決大數據問題的一個主要手段,隨着愈來愈多的分佈式的服務,如何在分佈式的系統中對這些服務作協調變成了一個很棘手的問題。今天咱們就來看看如何使用C# ,利用開源對分佈式服務作協調。html
在對分佈式的應用作協調的時候,主要會碰到如下的應用場景:node
找到分佈式系統中存在那些可用的服務和節點linux
經過給定的名字知道到對應的資源git
如何在分佈式的節點中共享配置文件,保證一致性。github
當某一個節點出故障的時候,如何檢測到並通知其它節點, 或者把想用的服務轉移到其它的可用節點web
如何在衆多的節點中選舉一個領導者,來協調全部的節點json
如何經過鎖在分佈式的服務中進行同步bootstrap
如何在分佈式的服務中傳遞消息,以通知的形式對事件做出主動的響應windows
Consul 瀏覽器
Consul是用Go開發的分佈式服務協調管理的工具,它提供了服務發現,健康檢查,Key/Value存儲等功能,而且支持跨數據中心的功能。consul提供的一些關鍵特性:
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協議產生的,而且最終一致的。
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);
Consul的另外一個主要的功能是用於對分佈式的服務作管理,用戶能夠註冊一個服務,同時還提供對服務作健康檢測的功能。
服務定義:一個服務能夠經過提供服務定義配置文件或者經過調用HTTP API來動態的增長、刪除、修改服務。
服務查詢:一旦agent啓動後,而且服務已經同步,咱們就可使用DNS或者HTTP API來進行查詢了。
服務升級:服務定義的升級能夠經過先修改服務定義配置文件,而後給agent發送一個SIGHUP信號便可,這樣容許你在升級服務時,而不會產生agent宕機時間或者服務不可達。或者經過HTTP API接口來動態的增長、刪除、修改服務。
Consul支持三種Check的模式:
C# API提供對應的接口
Consul的Health Check,經過調用腳本,HTTP或者主動上報的方式檢查服務的狀態,更爲靈活,能夠得到等多的信息,可是也須要作更多的工做。
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功能,能夠很方便的實現領導選舉和鎖的功能。
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