consul簡介
- Consul 是一個支持多數據中心分布式高可用的服務發現和配置共享的服務軟件,由 HashiCorp 公司用 Go 語言開發, 基於 Mozilla Public License 2.0 的協議進行開源. Consul 支持健康檢查,並允許 HTTP 和 DNS 協議調用 API 存儲鍵值對.
- 一致性協議采用 Raft 算法,用來保證服務的高可用. 使用 GOSSIP 協議管理成員和廣播消息, 並且支持 ACL 訪問控制.
- Consul 的方案更 "一站式",內置了服務注冊與發現框架、分布一致性協議實現、健康檢查、Key/Value 存儲、多數據中心方案,不再需要依賴其他工具(比如 ZooKeeper 等)。使用起來也較為簡單。Consul 用 Golang 實現,因此具有天然可移植性(支持 Linux、windows 和 Mac OS X);安裝包僅包含一個可執行文件,方便部署,與 Docker 等輕量級容器可無縫配合
使用場景
- docker 實例的注冊與配置共享
- coreos 實例的注冊與配置共享
- vitess 集群
- SaaS 應用的配置共享
- 與 confd 服務集成,動態生成 nginx 和 haproxy 配置文件
產品對比
同類工具有以下這些
etcd Distributed reliable key-value store for the most critical data of a distributed system
zookeeper Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination.
相同點
- 架構類似,都有服務節點,而這些服務節點的操作都要求達到節點的仲裁數(通常,節點的仲裁數遵循的是簡單多數原則
- 強一致性,用於構建復雜的分布式系統
不同點
- zooKeeper, etcd只提供一個原始的K/V值存儲,並要求開發人員構建他們自己的系統來提供服務發現功能,cosnul提供服務發現功能
- consul基於gossip的健康檢查機制脫穎而出。ZooKeeper健康檢查機制需要胖客戶端,增加了工作量。etcd無健康檢查功能
- consul使用Raft算法來保證一致性, 比復雜的Paxos算法更直接. 相比較而言, zookeeper采用的是 Paxos, 而 etcd 使用的則是 Raft.
- 支持多數據中心,內外網的服務采用不同的端口進行監聽。多數據中心集群可以避免單數據中心的單點故障, 而其部署則需要考慮網絡延遲, 分片等情況等. zookeeper和etcd 均不提供多數據中心功能的支持.
- 支持 http 和 dns 協議接口. zookeeper的集成較為復雜, etcd 只支持 http 協議.
- 官方提供web管理界面, etcd 無此功能
架構

術語解釋
Consul集群間使用了GOSSIP協議通信和raft一致性算法。
- Agent——agent是一直運行在Consul集群中每個成員上的守護進程。通過運行consul agent來啟動。agent可以運行在client或者server模式。指定節點作為client或者server是非常簡單的,除非有其他agent實例。所有的agent都能運行DNS或者HTTP接口,並負責運行時檢查和保持服務同步。
- Client——一個Client是一個轉發所有RPC到server的代理。這個client是相對無狀態的。client唯一執行的后台活動是加入LAN gossip池。這有一個最低的資源開銷並且僅消耗少量的網絡帶寬。
- Server——一個server是一個有一組擴展功能的代理,這些功能包括參與Raft選舉,維護集群狀態,響應RPC查詢,與其他數據中心交互WAN gossip和轉發查詢給leader或者遠程數據中心。
- DataCenter——我們定義數據中心為一個私有的,低延遲和高帶寬的一個網絡環境。
- Consensus——一致性,使用Consensus來表明就leader選舉和事務的順序達成一致。為了以容錯方式達成一致,一般有超過半數一致則可以認為整體一致。Consul使用Raft實現一致性,進行leader選舉,在consul中的使用bootstrap時,可以進行自選,其他server加入進來后bootstrap就可以取消。
- Gossip——Consul建立在Serf的基礎之上,它提供了一個用於多播目的的完整的gossip協議。Serf提供成員關系,故障檢測和事件廣播。Serf是去中心化的服務發現和編制的解決方案,節點失敗偵測與發現,具有容錯、輕量、高可用的特點。
- LAN Gossip——
Consul中的每個數據中心有一個LAN池,它包含了這個數據中心的所有成員,包括clients和servers。LAN池用於以下幾個目的:
成員關系信息允許client自動發現server, 減少了所需要的配置量。
分布式失敗檢測機制使得由整個集群來做失敗檢測這件事, 而不是集中到幾台機器上。
gossip池使得類似領導人選舉這樣的事件變得可靠而且迅速。
- WAN Gossip——
WAN池是全局唯一的,因為所有的server都應該加入到WAN池中,無論它位於哪個數據中心。由WAN池提供的成員關系信息允許server做一些跨數據中心的請求。一體化的失敗檢測機制允許Consul優雅地去處理:整個數據中心失去連接, 或者僅僅是別的數據中心的某一台失去了連接。
- RPC——遠程過程調用。這是一個允許client請求server的請求/響應機制。
架構分解
- 首先,我們可以看到有兩個數據中心,標簽為"Datacenter 1"和"Datacenter 2"。consul對多數據中心提供最高等級的支持並預期這將成為普遍情況。
- 在每個數據中心內,混合有客戶端和服務器。預期由3到5個服務器。強調在失敗情況下的可達到和性能之間的平衡,因為添加更多機器會導致一致性變得日益緩慢。不過,對於客戶端的數量沒有限制,而且可以很容易的擴展到成千上萬。
- 在一個數據中心內的所有節點加入一個gossip 協議。這意味着對於一個給定的數據中心,有一個包含所有節點的gossip池。這服務於幾個目的:
- 首先,不需要用服務器地址來配置客戶端;發現是自動完成的。
- 其次,檢測節點失敗的工作不是放置在服務器上,而是分布式的。這使得失敗檢測比心跳機制更加可擴展。
- 另外,當重要事件比如leader選舉發生時它被用來作為消息層(messaging layer)來通知。
- 每個數據中心中的服務器是單個Raft 端集合(peer set)的所有組成部分。這意味着他們一起工作來選舉leader,一個有額外職責的被選定的服務器。leader負責處理所有請求和事務。事務也必須復制到所有作為一致協議一部分的端(peer)。因為這個要求,當一個非leader服務器收到RPC請求時,它轉發請求到集群leader。
- 服務器節點也作為廣域網 gossip 協議池的一部分運作。這個池和局域網池有所不同,因為它為因特網的高延遲做了優化並預期只包含其他consul服務器(注:特指在其他數據中心中的consul服務器,見圖中的"Datacenter 2")節點。這個池的目的是容許數據中心們以低接觸(low-touch)風格相互發現。上線一個新的數據中心和加入現有的廣域網gossip一樣容易。因為服務器都在全體經營這個池,池可以開啟跨數據中心請求。當服務器收到一個給不同數據中心的請求時,它轉發請求到正確的數據中心中的任意服務器。這個服務器可能隨即轉發給本地leader。
- 這使得數據中心之間的耦合的非常低。而因為失敗檢測,連接緩存和多路通訊,跨數據中心請求相對比較快而可靠。
Gossip協議
- Gossip算法如其名,靈感來自辦公室八卦,只要一個人八卦一下,在有限的時間內所有的人都會知道該八卦的信息,這種方式也與病毒傳播類似,因此Gossip有眾多的別名“閑話算法”、“疫情傳播算法”、“病毒感染算法”、“謠言傳播算法”。
- 但Gossip並不是一個新東西,之前的泛洪查找、路由算法都歸屬於這個范疇,不同的是Gossip給這類算法提供了明確的語義、具體實施方法及收斂性證明。
- http://blog.csdn.net/u012422829/article/details/77828870
Anti-Entropy(反熵)
- Consule 使用一個高級的方式來維護 service 和 health 信息的方法。Anti-Entropy(反熵 ) 機制被用來保證在不同節點上的備份(replica)都持有最新版本
- Agent
- 每個Consul agent維護它自己的服務集合以及檢查注冊和健康信息。agent負責執行自己的健康檢查和更新本地狀態。
- Catalog
- Consul的服務發現基於一個服務目錄。這個目錄是通過聚合agents提交的信息形成的。目錄維護了集群的高級視圖,它包括哪些服務可用,哪些節點允許這些服務,健康信息等等。目錄是用來展示這些信息的,可以通過各種Consul提供的接口,包含DNS和HTTP。
- 與agent相比,目錄上下文中的服務和檢查的字段更為有限。這是因為目錄只服務於記錄和返回關於服務,節點和健康的信息。
- 只有server節點維護目錄。這是因為目錄是通過Raft日志復制來提供一個統一的集群視圖。
- http://blog.mallux.me/2017/03/19/consul/
- http://www.voidcn.com/article/p-oqtnkvov-ye.html
一致性Raft
- Consul使用Raft算法實現分布式存儲的一致性。Raft節點在集群中有follower,candidate或leader三種狀態,初始為follower,在這個狀態下節點可以接收來自leader的日志單元和投票選leader。如果一段時間內收不到來自leader的心跳,則升級為candidate向集群所有node發送投票邀請,如果candidate收到過半節點的投票則升級為leader,leader負責接收日志單元並復制給所有follower
- 集群當選出leader后才能接收新的日志單元,節點收到日志時把日志轉發給leader,leader將日志保存到本地存儲復制給所有follower,當超過半數的follower成功復制后日志單元狀態變為‘committed’,進而交給狀態機去執行。然后leader會將日志單元的committ狀態發送給所有follower讓他們來更新到各自狀態機。
- Consul自動的通過快照機制將Raft日志壓縮來避免其無限增長
- 在consul集群里,只有server結點通過Raft算法進行數據一致性管理,原因是Raft集群的結點數量不能太多(在3-5),如果client也參與到Raft那么隨着集群結點數量增加,在Raft算法下集群效率會下降,client結點只是將數據請求轉發給server
Raft啟動方式
- Raft集群的啟動方式有兩種,其中一種直接的辦法是用個配置文件記錄所有server的列表,每個server啟動后用這個靜態的列表作為Raft的server,但這需要所有server維護一個靜態的配置文件
- ‘-bootstrap’參數,如果集群先啟動一個server並且他優先成為leader(Consul在這里做了特殊設置,讓這個bootstrap server從log中恢復成leader狀態),之后加入的所有server一直是follower狀態。但這還有個問題,就是還是得固定一台server成為第一個leader,啟動參數必須與其他server不同(必須帶有-bootstrap)
- ‘-bootstrap-expect’參數,所有server都用同一參數’-boostrap-expect N’說明集群的server個數為N,在有N個server join進來后,cluster開始啟動raft邏輯選主。注意,N一定要與server總數相同,否則會出現split-brain(雙主)問題,比如N=3 兒集群server總數為7,就很可能出現兩個leader的情況。
讀操作一致性
- 對於讀操作,consul支持多種一致性模式:
- ‘default’, 這種模式下如果leader因為與成員分離導致新的leader被選出的情況下,雖然舊的leader不能再提交日志,但還可以負責進行讀取操作,這回導致部分讀取的數據是過期的。但這種狀態不會維持多長時間,因為舊的leader的狀態很快就會降級為follower
- ‘consistent’,這種模式下要求leader給follower發消息確認仍然是leader,這就造成了讀取操作時多了一步操作增加了延遲
- ‘stale’,這個模式下每個server都可以負責讀取,這就導致讀出來的數據因為還未在leader把數據復制到全部follower時被讀出兒造成不一致,但這種情況也是少數,並且效率會非常快,並且即便沒有leader的情況下還能夠提供讀操作
健康檢查
- Agent的一個重要任務是做系統級和程序級的健康檢測,檢測通過配置文件或HTTP接口來定義並被保存到Agent所運行的節點
- 定時腳本檢查(script+Interval), 調用一個第三方的程序進行健康檢測,使用退出碼或標准輸出來表明檢測結果(類似Nagios), 輸出內容不能超過4K,默認的檢查超時時間是30秒,可以通過配置文件里的”timeout”來定義。Agent使用enable_script_checks參數來打開這種檢查
- 腳本退出碼與檢測結果對應關系:
- 0, passing
- 1, warning
- other, failing
- 腳本的任何輸出內容會被保存到消息的‘Output’字段, Agent啟動后
- 定時HTTP檢查(HTTP+Interval), 定時通過HTTP GET調用指定的URL,根絕HTTP返回碼判斷服務狀態。‘2xx’表示通過檢查,‘429’表示警告,其余均表示故障。默認情況下http請求的timeout與檢查的interval相同,最長為10秒。可以通過‘timeout’來在配置文件里設置。檢查返回的內容大小不能超過4K,超過部分會被截斷。默認情況下支持SSL,可以通過tls_skip_verify來關掉。
- 定時TCP檢查(TCP+Interval), 定時通過TCP連接檢查指定host/IP和端口,根據是否能夠建立連接成功與否判定service狀態,成功連接表示service正常,否則表示事態危急. 默認超時時間10秒。
- TTL檢查,通過服務主動的定時更新TTL,超過時間的定位service故障。
- 定時Docker檢查,通過調用常駐docker里的一個檢查程序來進行,這個程序通過調用Docker Exec API來啟動,需要consul agent具有調用Docker HTTP API或Unix Socket的權限。consul用 DOCKER_HOST 來定位Docker API端點,檢查程序運行完后要返回適當的退出碼和輸出,輸出內容不能超過4K。Agent需要通過enable_script_check來打開這種檢查
- 默認會將check的狀態設置為‘critical’,這是防止服務在沒有被檢查前就被加入到調用這個服務的系統里
狀態監視
- 使用Whach可以監視KV、nodes、service、checks等對象的變化,當有更新時會觸發watch定義的可執行的handler。
- Watch通過阻塞的HTTP API實現,Agent會根據調用相應api請求自動監視指定內容,當有變化時通知handler
- Watch還可以加入到Agent的配置文件中的watches生成
- watch還可以通過‘consule watch’命令來直接運行並把結果輸出到處理程序
- 當watch監控到數據的更新,可以調用一個handler還做后續處理,watch會將監控的結果以JSON格式發送給handler的標准輸入(stdin), watch不同的對象結果的格式會不同
- watch的類型:
- Key
- keprefix
- services
- nodes
- service
- checks
- event
Session會話
- Consul 提供了一個可用於 構建分布式鎖 的會話(session)機制。 Session 充當節點、運行狀況檢查和鍵/值數據之間的綁定層。 它們旨在提供細粒度的鎖定,並受到松散耦合的分布式系統的分布式鎖服務(The Chubby Lock Service for Loosely-Coupled Distributed Systems)的大量啟發。
- Consul 中的 session 表示具有非常特定語義的 contract 。 當構建會話時,可以提供節點名稱、健康檢查列表、行為、TTL 和 鎖定延遲。 新構造的 session 具有可用於識別它的命名 ID。 此 ID 可與 KV 存儲一起使用以獲取鎖:用於互斥的咨詢機制。
- Consule 提供的 contract ,在下列任何情況下,會話將失效:
- 節點已取消注冊
- 任何健康檢查都被取消注冊
- 任何健康檢查都進入臨界狀態
- 會話被明確銷毀
- TTL 到期(如果適用)
- 當 session 無效時,會被銷毀,不能再使用。 相關鎖的操作取決於在創建時指定的行為。 Consul 支持 release 和 delete 行為。 如果未指定任何內容,則 release 行為是缺省值。
命令
kv - Key/Value存儲
agent - Agent控制
catalog - 管理nodes和services
health - 管理健康監測
session - Session操作
acl - ACL創建和管理
event - 用戶Events
status - Consul系統狀態
Agent API
/v1/agent/checks : 返回本地agent注冊的所有檢查(包括配置文件和HTTP接口)
/v1/agent/services : 返回本地agent注冊的所有 服務
/v1/agent/members : 返回agent在集群的gossip pool中看到的成員
/v1/agent/self : 返回本地agent的配置和成員信息
/v1/agent/join/<address> : 觸發本地agent加入node
/v1/agent/force-leave/<node>>: 強制刪除node
/v1/agent/check/register : 在本地agent增加一個檢查項,使用PUT方法傳輸一個json格式的數據
/v1/agent/check/deregister/<checkID> : 注銷一個本地agent的檢查項
/v1/agent/check/pass/<checkID> : 設置一個本地檢查項的狀態為passing
/v1/agent/check/warn/<checkID> : 設置一個本地檢查項的狀態為warning
/v1/agent/check/fail/<checkID> : 設置一個本地檢查項的狀態為critical
/v1/agent/service/register : 在本地agent增加一個新的服務項,使用PUT方法傳輸一個json格式的數據
/v1/agent/service/deregister/<serviceID> : 注銷一個本地agent的服務項
Catalog API
/v1/catalog/register : Registers a new node, service, or check
/v1/catalog/deregister : Deregisters a node, service, or check
/v1/catalog/datacenters : Lists known datacenters
/v1/catalog/nodes : Lists nodes in a given DC
/v1/catalog/services : Lists services in a given DC
/v1/catalog/service/<service> : Lists the nodes in a given service
/v1/catalog/node/<node> : Lists the services provided by a node
Health API
/v1/healt/node/<node>: 返回node所定義的檢查,可用參數?dc=
/v1/health/checks/<service>: 返回和服務相關聯的檢查,可用參數?dc=
/v1/health/service/<service>: 返回給定datacenter中給定node中service
/v1/health/state/<state>: 返回給定datacenter中指定狀態的服務,state可以是"any", "unknown", "passing", "warning", or "critical",可用參數?dc=
Session API
/v1/session/create: Creates a new session
/v1/session/destroy/<session>: Destroys a given session
/v1/session/info/<session>: Queries a given session
/v1/session/node/<node>: Lists sessions belonging to a node
/v1/session/list: Lists all the active sessions
ACL API
/v1/acl/create: Creates a new token with policy
/v1/acl/update: Update the policy of a token
/v1/acl/destroy/<id>: Destroys a given token
/v1/acl/info/<id>: Queries the policy of a given token
/v1/acl/clone/<id>: Creates a new token by cloning an existing token
/v1/acl/list: Lists all the active tokens
Event API
/v1/event/fire/<name>: 觸發一個新的event,用戶event需要name和其他可選的參數,使用PUT方法
/v1/event/list: 返回agent知道的events
Status API
/v1/status/leader : 返回當前集群的Raft leader
/v1/status/peers : 返回當前集群中參與投票的節點
自定義事件
Event:
consul event -name=test -http-addr=localhost:8500
consul watch -type=event -name=test "echo 'see it'”
Key:
curl -XPUT 'http://localhost:8500/v1/kv/web/k1' -d '{"name":"mm"}’
consul watch -type=key –key=web/k1 "echo 'see it'”
更多內容見:
http://blog.csdn.net/younger_china/article/details/52243799
Why client per node
SRV 中的target實際指向了注冊節點的域名,所以說明 consul 的 DNS 規則是不管你service 注冊的時候無論你怎么提交自己的 IP, 在 DNS 上,永遠以注冊的Consul節點的 IP 作為 Service 的實際 IP,都是 SRV 規則導致的,
所以總結一下,在本地部署 consul Client 的原因是標識 Service 的實際 IP, 這確實也是逼不得已的方式,如果使用 HTTPDNS 的話,效率不但低,而且算是一個私有協議,不利於和基礎環境的融合.
