consul配置與實戰(zhàn)

上一篇提到,項目用的分布式服務(wù)發(fā)現(xiàn)與注冊組件是consul,這篇文章主要來講下consul組件在項目中的應(yīng)用以及相關(guān)介紹。本文以官方文檔為主要參考consul文檔

1. consul介紹

consul是一個服務(wù)管理軟件,主要功能如下:

  1. 支持多數(shù)據(jù)中心下,分布式高可用的,服務(wù)發(fā)現(xiàn)和配置共享。
  2. consul支持健康檢查,允許存儲鍵值對。
  3. 一致性協(xié)議采用Raft算法,用來保證服務(wù)的高可用。
  4. 成員管理和消息廣播采用GOSSIP協(xié)議,支持ACL訪問控制。

1.1 服務(wù)注冊與發(fā)現(xiàn)

服務(wù)注冊是一個服務(wù)將其位置信息在“中心注冊節(jié)點”注冊的過程。該服務(wù)一般會將它的主機IP地址以及端口號進行注冊,有時也會有服務(wù)訪問的認證信息,使用協(xié)議,版本號,以及關(guān)于環(huán)境的一些細節(jié)信息。
而服務(wù)發(fā)現(xiàn)可以讓一個應(yīng)用或者組件發(fā)現(xiàn)其運行環(huán)境以及其它應(yīng)用或組件的信息。用戶配置一個服務(wù)發(fā)現(xiàn)工具就可以將實際容器跟運行配置分離開。常見配置信息包括:ip、端口號、名稱等。

在傳統(tǒng)情況下,當出現(xiàn)服務(wù)存在于多個主機節(jié)點上時,都會使用靜態(tài)配置的方法來實現(xiàn)服務(wù)信息的注冊。
而當在一個復(fù)雜的系統(tǒng)里,需要較強的可擴展性時,服務(wù)被頻繁替換時,為避免服務(wù)中斷,動態(tài)的服務(wù)注冊和發(fā)現(xiàn)就很重要。
服務(wù)注冊與發(fā)現(xiàn)的組件有很多,如Zookeeper、Etcd等。既可用于服務(wù)間的協(xié)調(diào),同時又可用于服務(wù)的注冊。

1.2 Consensus Protocol - Raft

Consul使用Consensus協(xié)議Raft提供一致性(Consistency)。本文只是簡單介紹在consul中的一致性,后面專門一篇寫raft。

raft算法
raft算法

首先,Raft是一種基于Paxos的Consensus算法。相比于Paxos,Raft設(shè)計采用了較少的狀態(tài),并且是一種更簡單、更易于理解的算法。
只有Server節(jié)點參與Raft,且是peer set的一員。所有的Client節(jié)點只是轉(zhuǎn)發(fā)請求到Server。這種設(shè)計的考慮是,當更多的成員加入到peer set中時,quorum的規(guī)模也會增加。可能會導(dǎo)致性能問題是等待quorum個節(jié)點log entry。
啟動Consul時,單個consul節(jié)點需要以bootstrap模式運行,該模式運行自我選舉為leader。一旦Leader被選出來,其他Server可以添加Peer set中,保持一致性和安全性。最終一些Server添加到集群,bootstrap模式需要禁用。
因為所有Server都是Peer set中的成員,它們都知道誰是Leader。當一個RPC請求到達某個非Leader Server節(jié)點,請求就會被轉(zhuǎn)發(fā)到Leader。如果RPC是一種query類型,這意味著它是只讀的,Leader會基于FSM當前生成相應(yīng)的結(jié)果,如果RPC是一種transaction類型,即修改狀態(tài),Leader產(chǎn)生一個新的日志條目,并基于Raft算法進行管理。一旦日志條目應(yīng)用于有限狀態(tài)機,transaction完成。
由于Raft的replication性質(zhì),性能對網(wǎng)絡(luò)延遲是非常敏感的。為此,每個數(shù)據(jù)中心選擇獨立的Leader和維護一個不關(guān)聯(lián)的peer set。數(shù)據(jù)按照數(shù)據(jù)中心進行劃分,所以每個Leader只負責在相應(yīng)數(shù)據(jù)中心的數(shù)據(jù)。當接收到一個遠程數(shù)據(jù)中心的請求時,請求會被轉(zhuǎn)發(fā)到相應(yīng)的Leader。這種設(shè)計在不犧牲一致性的情況實現(xiàn)較低延遲交易和更高的可用性。
雖然所有日志副本的寫入都是基于Raft,讀取更靈活。但為了支持開發(fā)人員可能需要的各種權(quán)衡,Consul支持3種不同的一致性模式。

  • Default,Raft采用Leader租賃模式,提供了一個時間窗口,在該時間段內(nèi),Leader角色是穩(wěn)定的。
  • consistent,無條件一致性
  • stale,這種模式允許在任何Server節(jié)點執(zhí)行讀取操作,無論它是不是Leader。

1.3 Group Membership Protocol - Gossip

Consul使用gossip協(xié)議管理成員關(guān)系、廣播消息到整個集群。詳情可參考Serf library
Consul利用兩個不同的gossip pool。局域網(wǎng)(LAN Pool)和廣域網(wǎng)(WAN Pool)。
每個Consul數(shù)據(jù)中心都有一個包含所有成員(Server和Client)的LAN gossip pool。LAN Pool有如下幾個目的:

  • 首先,成員關(guān)系允許Client自動發(fā)現(xiàn)Server節(jié)點,減少所需的配置量。
  • 其次,分布式故障檢測允許的故障檢測的工作在某幾個Server幾點執(zhí)行,而不是集中整個集群所有節(jié)點上。
  • 最后,gossip允許可靠和快速的事件廣播,如Leader選舉。

WAN Pool是全局唯一的,無論屬于哪一個數(shù)據(jù)中心,所有Server應(yīng)該加入到WAN Pool。由WAN Pool提供會員信息讓Server可節(jié)電執(zhí)行跨數(shù)據(jù)中心的請求。集成中故障檢測允許Consul妥善處理整個數(shù)據(jù)中心失去連接,或在遠程數(shù)據(jù)中心只是單個的Server節(jié)點。
所有這些功能都是通過利用Serf提供。從用戶角度來看,它是作為一個嵌入式庫提供這些功能。但其被Consul屏蔽,用戶無需關(guān)心。作為開發(fā)人員可以去了解這個庫是如何利用。

1.4 Session會話

上一篇文章snowflake升級版全局id生成中使用到了consul的KV存儲。
Consul提供session會話機制,可以用于構(gòu)建分布式鎖。session可以綁定到節(jié)點、健康檢查、KV數(shù)據(jù),目的是提供細粒度鎖。
KV存儲和會話的集成是使用會話的主要場景。必須在使用之前創(chuàng)建一個會話,然后使用它的ID。KV API支持acquire和release操作,acquire操作類似CAS操作,只有當鎖空閑時才會返回成功。當成功時,某個normal標識會更新,也會遞增LockIndex,當然也會更新session的信息。
如果在acquire操作時,與session相關(guān)的鎖已經(jīng)持有,那么LockIndex就不會遞增,但是key值會更新,這就允許鎖的當前持有者無需重新獲得鎖就可以更新key的內(nèi)容。
一旦獲得鎖,所需要經(jīng)release操作來釋放(使用相同的session)。Release操作也類似于CAS操作。如果給定的session無效,那么請求會失敗。需要特別注意的是,無需經(jīng)過session的創(chuàng)建者,lock也是可以被釋放的。這種設(shè)計是允許操作者干預(yù)來終止會話,在需要的時候。如上所述,會話無效也將導(dǎo)致所有被持有的鎖被釋放或刪除。當鎖被釋放時,LockIndex不會變化,但是session會被清空,并且ModifyIndex遞增。這些語義允許元組(Key,LockIndex,Session)作為一個獨特的“序列”。這個序列可以被傳遞和用于驗證請求是否屬于當前的鎖持有者。因為每次acquire 都會導(dǎo)致LockIndex遞增,即使同一會話中重新獲取鎖,該序列能夠檢測到陳舊的請求。同樣,如果會話失效,相應(yīng)的LockIndex將為空。
要清楚的是,這種鎖系統(tǒng)是純粹的咨詢。并不是強制Client必須獲取鎖再能執(zhí)行操作作。任何客戶端都可以在未獲得鎖的情況下讀取、寫入和刪除Key操作。它不是Consul用于保護系統(tǒng)的方法。

2. consul架構(gòu)

上面介紹了consul的技術(shù)內(nèi)幕。現(xiàn)在來講講consul的架構(gòu)。

consul
consul

拆解開這個體系,從每一個組件開始了解。首先,可以看到有兩個數(shù)據(jù)中心,分別標記為“one”和“two”。Consul是支持多數(shù)據(jù)中心一流,并且是常用業(yè)務(wù)場景。

每個數(shù)據(jù)中心都是由Server和client組成。建議有3~5臺Server,基于故障處理和性能的平衡之策。如果增加越多的機器,則Consensus會越來越慢。對client沒有限制,可以很容易地擴展到成千上萬或數(shù)萬。
同一個數(shù)據(jù)中心的所有節(jié)點都要加入Gossip協(xié)議。這意味著gossip pool包含給定數(shù)據(jù)中心的所有節(jié)點。有以下目的:首先,沒有必要為client配置服務(wù)器地址參數(shù);發(fā)現(xiàn)是自動完成的。第二,節(jié)點故障檢測的工作不是放置在服務(wù)器上,而是分布式的。這使故障檢測比心跳機制更可擴展性。第三,可用來作為消息層通知重要的事件,如leader選舉。

每個數(shù)據(jù)中心的服務(wù)器都是屬于一個Raft peer。這意味著,他們一起工作,選出一個的Leader,Leader server是有額外的職責。負責處理所有的查詢和事務(wù)。事務(wù)也必須通過Consensus協(xié)議復(fù)制到所有的伙伴。由于這一要求,當非Leader Server接收到一個RPC請求,會轉(zhuǎn)發(fā)到集群的leader。

Server節(jié)點也是作為WAN gossip pool的一部分。這個pool是與LAN gossip pool是不同的,它為具有更高延遲的網(wǎng)絡(luò)響應(yīng)做了優(yōu)化,并且可能包括其他consul集群的server節(jié)點。設(shè)計WANpool的目的是讓數(shù)據(jù)中心能夠以low-touch的方式發(fā)現(xiàn)彼此。將一個新的數(shù)據(jù)中心加入現(xiàn)有的WAN Gossip是很容易的。因為池中的所有Server都是可控制的,這也使跨數(shù)據(jù)中心的要求。當一個Serfer接收到不同的數(shù)據(jù)中心的要求時,它把這個請求轉(zhuǎn)發(fā)給相應(yīng)數(shù)據(jù)中心的任一Server。然后,接收到請求的Server可能會轉(zhuǎn)發(fā)給Leader。
多個數(shù)據(jù)中心之間是低耦合,但由于故障檢測、連接緩存復(fù)用、跨數(shù)據(jù)中心要求快速和可靠的響應(yīng)。

3. consul部署

3.1 docker安裝

docker安裝很簡單,筆者這邊是基于docker-compose的配置文件,只需要本地安裝好docker和docker-compose,docker-compose.yml如下:

version: '3'
services:
  consul:
    image: consul
    ports:
     - "8500:8500"
     - "8600:8600"
     - "8300:8300"

拉取consul得最新image,進行端口映射,暴露對外的端口8500,8300.

3.2 軟件安裝

  1. 從官網(wǎng)下載罪行的consul安裝包,https://www.consul.io/downloads.html
  2. 解壓consul_0.6.4_darwin_amd64.zip。
  3. 將解壓后的二進制文件consul拷貝到/usr/local/bin下。
  4. 寫配置文件。
    服務(wù)注冊的配置文件如下:
{
  "service": {
    "name": "redis",
    "tags": ["master"],
    "address": "1192.168.1.100",
    "port": 8000,
    "enableTagOverride": false,
    "check": {  
        "id": "redis",  
        "name": "redis on port 8000",  
        "tcp": "localhost:8000",  
        "interval": "10s",  
        "timeout": "1s"  
  }
  }
}

如上配置注冊了Redis的8000端口,并帶有tcp的health check。

節(jié)點的配置文件:

{
  "datacenter": "east-cn",
  "data_dir": "/opt/consul",
  "log_level": "INFO",
  "node_name": "redis",
  "server": true,
  "addresses": {
    "https": "192.168.1.100"
  },
  "ports": {
    "https": 0
  },
  "ui": true,
  "retry-join": [
]
}

當加載配置選項時,consul是按照詞典順序從所有配置文件或目錄中加載。比如,a.json會先于e.json處理。后面設(shè)定的配置選項會合并到前面的配置集合中,如果存在重復(fù)的配置選項則會覆蓋。當然,在某些情況下,比如事件處理程序,后面處理程序會追加到現(xiàn)有的配置選項中,形成事件處理程序列表。

3.3 啟動

具體啟動文檔見configuration
如:

consul agent -server -config-dir /etc/consul.d -bind=192.168.1.100
    -config-dir /etc/consul.d
  • config-dir
    需要加載的配置文件目錄,consul將加載目錄下所有后綴為“.json”的文件,加載順序為字母順序,文件中配置選項合并方式如config-file。該參數(shù)可以多次配置。目錄中的子目錄是不會加載的。

  • data-dir
    此目錄是為Agent存放state數(shù)據(jù)的。是所有Agent需要的,該目錄應(yīng)該存放在持久存儲中(reboot不會丟失),對于server角色的Agent是很關(guān)鍵的,需要記錄集群狀態(tài)。并且該目錄是支持文件鎖。

  • server
    設(shè)置Agent是server模式還是client模式。Consul agent有兩種運行模式:Server和Client。這里的Server和Client只是Consul集群層面的區(qū)分,與搭建在Cluster之上 的應(yīng)用服務(wù)無關(guān)。Consule Server模式agent節(jié)點用于采用raft算法維護Consul集群的狀態(tài),官方建議每個Consul Cluster至少有3個或以上的運行在Server mode的Agent,Client節(jié)點不限。

其他常用的還有:

  • client
    將綁定到client接口的地址,可以是HTTP、DNS、RPC服務(wù)器。默認為“127.0.0.1”,只允許回路連接。RPC地址會被其他的consul命令使用,比如consul members,查詢agent列表

  • node
    節(jié)點在集群的名字,在集群中必須是唯一的。默認為節(jié)點的Hostname。

  • bootstrap
    設(shè)置服務(wù)是否為“bootstrap”模式。如果數(shù)據(jù)中心只有1個server agent,那么需要設(shè)置該參數(shù)。從技術(shù)上來講,處于bootstrap模式的服務(wù)器是可以選擇自己作為Raft Leader的。在consul集群中,只有一個節(jié)點可以配置該參數(shù),如果有多個參數(shù)配置該參數(shù),那么難以保證一致性。

  • bind
    用于集群內(nèi)部通信的IP地址,與集群中其他節(jié)點互連可通。默認為“0.0.0.0”,consul將使用第一個有效的私有IPv4地址。如果指定“[::]”,consul將使用第一個有效的公共IPv6地址。使用TCP和UDP通信。注意防火墻,避免無法通信。

3.4 結(jié)果

在開啟了"ui": trueserver主機上,如http://192.168.1.100:8500/ui查看注冊中心的服務(wù)。
demo ui如下:

consului
consului

4. 總結(jié)

本文介紹了consul的一些內(nèi)幕及consul配置相關(guān),并對項目中的一些實際配置進行展示。希望能夠幫助大家對consul相關(guān)的知識有所了解,并對于入門配置consul和實際應(yīng)用有所知道。個人認為,consul原理還是簡單易懂的,集群的配置也不復(fù)雜,安利大家使用。后面會再寫一篇介紹Spring cloud中集成和使用consul組件作為注冊與發(fā)現(xiàn)中心。

歡迎關(guān)注我的公眾號

微信公眾號

參考文獻

consul文檔
consul中文翻譯

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容