基於Docker + Consul + Registrator的服務註冊與發現集羣搭建

前言

近年微服務架構在互聯網應用領域中越來越火,引入微服務主要解決了單體應用多個模塊的緊耦合沒法擴展運維困難等問題。微服務架構就是按照功能粒度將業務模塊進行垂直拆分,對單體應用自己進行服務化組件化,每一個組件單獨部署爲小應用(從DBUI)。微服務與微服務之間經過Service API進行交互,同時爲了支持水平擴展性能提高服務可用性,單個服務容許同時部署一個或者多個服務實例。在運行時,每一個實例一般是一個雲虛擬機或者Docker容器node

微服務系統內部多個服務的實例之間如何通訊?如何感知到彼此的存在和銷燬?生產者服務如何知道消費者服務的地址?如何實現服務與註冊中心的解耦?這就須要一個第三方的服務註冊中心,提供對生產者服務節點的註冊管理和消費者服務節點的發現管理。linux


正文

1. 服務發現與註冊

1.1. 具體流程

  • 服務註冊中心:做爲整個架構中的核心,要支持分佈式持久化存儲註冊信息變更實時通知消費者。
  • 服務提供者: 服務以 docker 容器化方式部署(實現服務端口動態生成),能夠經過 docker-compose 的方式來管理。經過 Registrator 檢測到 docker 進程信息以完成服務的自動註冊
  • 服務消費者:要使用服務提供者提供的服務,和服務提供者每每是動態相互轉位置的。

一個較爲完整的服務註冊與發現流程以下:算法

  1. 註冊服務:服務提供者到註冊中心註冊
  2. 訂閱服務:服務消費者到註冊中心訂閱服務信息,對其進行監聽
  3. 緩存服務列表:本地緩存服務列表,減小與註冊中心的網絡通訊;
  4. 調用服務:先查找本地緩存,找不到再去註冊中心拉取服務地址,而後發送服務請求;
  5. 變動通知:服務節點變更時 (新增刪除等),註冊中心將通知監聽節點,更新服務信息。

1.2. 相關組件

一個服務發現系統主要由三部分組成:docker

  1. 註冊器(registrator):根據服務運行狀態,註冊/註銷服務。主要要解決的問題是,什麼時候發起註冊/註銷動做。
  2. 註冊表(registry):存儲服務信息。常見的解決方案有zookeeper、etcd、cousul等。
  3. 發現機制(discovery):從註冊表讀取服務信息,給用戶封裝訪問接口。

1.3. 第三方實現

對於第三方的服務註冊與發現的實現,現有的工具主要有如下三種:編程

  1. zookeeper:一個高性能、分佈式應用程序協調服務,用於名稱服務、分佈式鎖定、共享資源同步和分佈式配置管理。
  2. Etcd:一個採用HTTP協議的健/值對存儲系統,主要用於共享配置和服務發現,提供的功能相對Zookeeper和Consul相對簡單。
  3. Consul:一個分佈式高可用的服務發現和配置共享的軟件,支持服務發現與註冊、多數據中心、健康檢查和分佈式鍵/值存儲。

簡單對比:json

與Zookeeper和etcd不同,Consul內嵌實現了服務發現系統,不須要構建本身的系統或使用第三方系統,客戶只須要註冊服務,並經過DNS或HTTP接口執行服務發現。bootstrap

2. Consul和Registrator

2.1. Consul簡介

Consul是什麼ubuntu

Consul 是一種分佈式的、高可用支持水平擴展的的服務註冊與發現工具。它大體包括如下特性:後端

  • 服務發現Consul 經過 DNS 或者 HTTP 接口使服務註冊和服務發現變的很容易。一些外部服務,例如 saas 提供的也能夠同樣註冊;
  • 健康檢查:健康檢測使 consul 能夠快速的告警在集羣中的操做。和服務發現的集成,能夠防止服務轉發到故障的服務上面;
  • 鍵/值存儲:一個用來存儲動態配置的系統。提供簡單的 HTTP 接口,能夠在任何地方操做;
  • 多數據中心:支持多數據中心以免單點故障,內外網的服務採用不一樣的端口進行監聽。而其部署則須要考慮網絡延遲, 分片等狀況等。zookeeperetcd均不提供多數據中心功能的支持;
  • 一致性算法:採用 Raft 一致性協議算法,比Paxos算法好用。 使用 GOSSIP 協議管理成員和廣播消息, 而且支持 ACL 訪問控制;
  • 服務管理Dashboard:提供一個 Web UI 的服務註冊於健康狀態監控的管理頁面。

Consul的幾個概念緩存

下圖是Consul官方文檔提供的架構設計圖:

圖中包含兩個Consul數據中心,每一個數據中心都是一個consul的集羣。在數據中心1中,能夠看出consul的集羣是由NSERVER,加上MCLIENT組成的。而不論是SERVER仍是CLIENT,都是consul集羣的一個節點。全部的服務均可以註冊到這些節點上,正是經過這些節點實現服務註冊信息的共享。除了這兩個,還有一些小細節 一一 簡單介紹。

  • CLIENT

CLIENT表示consulclient模式,就是客戶端模式。是consul節點的一種模式,這種模式下,全部註冊到當前節點的服務會被轉發SERVER節點,自己是不持久化這些信息。

  • SERVER

SERVER表示consulserver模式,代表這個consul是個server節點。這種模式下,功能和CLIENT都同樣,惟一不一樣的是,它會把全部的信息持久化的本地。這樣遇到故障,信息是能夠被保留的。

  • SERVER-LEADER

中間那個SERVER下面有LEADER的描述,代表這個SERVER節點是它們的老大。和其它SERVER不同的一點是,它須要負責同步註冊信息給其它的SERVER,同時也要負責各個節點健康監測

  • 其它信息

其它信息包括各個節點之間的通訊方式,還有一些協議信息算法。它們是用於保證節點之間的數據同步實時性要求等等一系列集羣問題的解決。這些有興趣的本身看看官方文檔。

2.2. Registrator簡介

什麼是Registrator Registrator是一個獨立於服務註冊表的自動服務註冊/註銷組件,通常以Docker container的方式進行部署。Registrator會自動偵測它所在的宿主機上的全部Docker容器狀態(啓用/銷燬),並根據容器狀態到對應的服務註冊列表註冊/註銷服務。

事實上,Registrator經過讀取同一臺宿主機的其餘容器Container環境變量進行服務註冊健康檢查定義等操做。

Registrator支持可插拔式服務註冊表配置,目前支持包括Consul, etcdSkyDNS 2三種註冊工具。

2.3. Docker安裝Consul集羣

2.3.1. 集羣節點規劃

我本地的使用的是Ubuntu16.04的虛擬機:

容器名稱 容器IP地址 映射端口號 宿主機IP地址 服務運行模式
node1 172.17.0.2 8500 -> 8500 192.168.127.128 Server Master
node2 172.17.0.3 9500 -> 8500 192.168.127.128 Server
node3 172.17.0.4 10500 -> 8500 192.168.127.128 Server
node4 172.17.0.5 11500 -> 8500 192.168.127.128 Client

2.3.2. Consul集羣安裝

Consul的配置參數信息說明:

參數列表 參數的含義和使用場景說明
advertise 通知展示地址用來改變咱們給集羣中的其餘節點展示的地址,通常狀況下-bind地址就是展示地址
bootstrap 用來控制一個server是否在bootstrap模式,在一個datacenter中只能有一個server處於bootstrap模式,當一個server處於bootstrap模式時,能夠本身選舉爲raft leader
bootstrap-expect 在一個datacenter中指望提供的server節點數目,當該值提供的時候,consul一直等到達到指定sever數目的時候纔會引導整個集羣,該標記不能和bootstrap共用
bind 該地址用來在集羣內部的通信IP地址,集羣內的全部節點到地址都必須是可達的,默認是0.0.0.0
client consul綁定在哪一個client地址上,這個地址提供HTTP、DNS、RPC等服務,默認是127.0.0.1
config-file 明確的指定要加載哪一個配置文件
config-dir 配置文件目錄,裏面全部以.json結尾的文件都會被加載
data-dir 提供一個目錄用來存放agent的狀態,全部的agent容許都須要該目錄,該目錄必須是穩定的,系統重啓後都繼續存在
dc 該標記控制agent容許的datacenter的名稱,默認是dc1
encrypt 指定secret key,使consul在通信時進行加密,key能夠經過consul keygen生成,同一個集羣中的節點必須使用相同的key
join 加入一個已經啓動的agent的ip地址,能夠屢次指定多個agent的地址。若是consul不能加入任何指定的地址中,則agent會啓動失敗,默認agent啓動時不會加入任何節點
retry-interval 兩次join之間的時間間隔,默認是30s
retry-max 嘗試重複join的次數,默認是0,也就是無限次嘗試
log-level consul agent啓動後顯示的日誌信息級別。默認是info,可選:trace、debug、info、warn、err
node 節點在集羣中的名稱,在一個集羣中必須是惟一的,默認是該節點的主機名
protocol consul使用的協議版本
rejoin 使consul忽略先前的離開,在再次啓動後仍舊嘗試加入集羣中
server 定義agent運行在server模式,每一個集羣至少有一個server,建議每一個集羣的server不要超過5個
syslog 開啓系統日誌功能,只在linux/osx上生效
pid-file 提供一個路徑來存放pid文件,可使用該文件進行SIGINT/SIGHUP(關閉/更新)agent

2.4. Docker安裝Consul集羣

2.4.1. 拉取consul官方鏡像

madison@ubuntu:~$ docker pull consul:latest
複製代碼

2.4.2. 啓動Server節點

運行consul鏡像,啓動Server Master節點node1

node1:

madison@ubuntu:~$ docker run -d --name=node1 --restart=always \
             -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' \
             -p 8300:8300 \
             -p 8301:8301 \
             -p 8301:8301/udp \
             -p 8302:8302/udp \
             -p 8302:8302 \
             -p 8400:8400 \
             -p 8500:8500 \
             -p 8600:8600 \
             -h node1 \
             consul agent -server -bind=172.17.0.2 -bootstrap-expect=3 -node=node1 \
             -data-dir=/tmp/data-dir -client 0.0.0.0 -ui

複製代碼

查看node1的日誌,追蹤運行狀況:

如今集羣中尚未選舉leader節點,繼續啓動其他兩臺Server節點node2node3

node2:

madison@ubuntu:~$ docker run -d --name=node2 --restart=always \
             -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' \
             -p 9300:8300  \
             -p 9301:8301 \
             -p 9301:8301/udp \
             -p 9302:8302/udp \
             -p 9302:8302 \
             -p 9400:8400 \
             -p 9500:8500 \
             -p 9600:8600 \
             -h node2 \
             consul agent -server -bind=172.17.0.3 \
             -join=192.168.127.128 -node-id=$(uuidgen | awk '{print tolower($0)}') \
             -node=node2 \
             -data-dir=/tmp/data-dir -client 0.0.0.0 -ui
複製代碼

查看node2節點的進程啓動日誌:

node3:

madison@ubuntu:~$ docker run -d --name=node3 --restart=always \
             -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' \
             -p 10300:8300  \
             -p 10301:8301 \
             -p 10301:8301/udp \
             -p 10302:8302/udp \
             -p 10302:8302 \
             -p 10400:8400 \
             -p 10500:8500 \
             -p 10600:8600 \
             -h node2 \
             consul agent -server -bind=172.17.0.4 \
             -join=192.168.127.128 -node-id=$(uuidgen | awk '{print tolower($0)}') \
             -node=node3 \
             -data-dir=/tmp/data-dir -client 0.0.0.0 -ui
複製代碼

查看node3節點的進程啓動日誌:

當3個Server節點都啓動並正常運行時,觀察node2node3的進程日誌,能夠發現node1被選舉爲leader節點,也就是這個數據中心Server Master

再次查看node1節點的進程啓動日誌:

觀察日誌發現,node2node3都成功join到了node1所在的數據中心dc1。當集羣中有3臺Consul Server啓動時,node1被選舉爲dc1中的主節點。而後,node1會經過心跳檢查的方式,不斷地對node2node3進行健康檢查。

2.4.4. 啓動Client節點

node4:

madison@ubuntu:~$ docker run -d --name=node4  --restart=always \
            -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}' \
            -p 11300:8300 \
            -p 11301:8301 \
            -p 11301:8301/udp \
            -p 11302:8302/udp \
            -p 11302:8302 \
            -p 11400:8400 \
            -p 11500:8500 \
            -p 11600:8600 \
            -h node4 \
            consul agent -bind=172.17.0.5 -retry-join=192.168.127.128  \
            -node-id=$(uuidgen | awk '{print tolower($0)}') \
            -node=node4 -client 0.0.0.0 -ui
複製代碼

查看node4節點的進程啓動日誌:

能夠發現:node4是以Client模式啓動運行的。啓動後完成後,把dc1數據中心中的以Server模式啓動的節點node1node2node3都添加到本地緩存列表中。當客戶端向node4發起服務發現的請求後,node4會經過RPC將請求轉發給Server節點中的其中一臺作處理。

2.4.5. 查看集羣狀態

madison@ubuntu:~$ docker exec -t node1 consul members
複製代碼

dc1數據中心中的4個節點node1, node2, node3node4分別成功啓動,Status表示他們的狀態,都爲alivenode1, node2, node3Server模式啓動,而node4Client模式啓動。

2.5. Docker安裝Registrator

2.5.1. 拉取Registrator的鏡像

madison@ubuntu:~$ docker pull gliderlabs/registrator:latest
複製代碼

2.5.2. 啓動Registrator節點

madison@ubuntu:~$ docker run -d --name=registrator \
             -v /var/run/docker.sock:/tmp/docker.sock \
             --net=host \
             gliderlabs/registrator -ip="192.168.127.128" consul://192.168.127.128:8500
複製代碼

--net指定爲host代表使用主機模式。 -ip用於指定宿主機的IP地址,用於健康檢查的通訊地址。 consul://192.168.127.128:8500: 使用Consul做爲服務註冊表,指定具體的Consul通訊地址進行服務註冊和註銷(注意:8500是Consul對外暴露的HTTP通訊端口)。

查看Registrator的容器進程啓動日誌:

Registrator在啓動過程完成了如下幾步操做:

  1. 查看Consul數據中心的leader節點,做爲服務註冊表;
  2. 同步當前宿主機的啓用容器,以及全部的服務端口;
  3. 分別將各個容器發佈的服務地址/端口註冊到Consul的服務註冊列表。

2.5.3. 查看Consul的註冊狀態

Consul提供了一個Web UI來可視化服務註冊列表通訊節點數據中心鍵/值存儲等,直接訪問宿主機的8500端口。

服務註冊列表

NODES節點下掛載着dc1數據中心中的全部的Consul節點,包括Consul ServerClient

通訊節點列表

啓動Registrator之後,宿主機中的全部容器把服務都註冊到ConsulSERVICES上,測試完成!


總結

單數據中心Consul集羣的搭建就完成了!!!後續章節我會介紹如何使用Registrator進行服務註冊的標籤化。而後經過docker部署多實例Web容器來實現基於HTTPRESTful Service和基於TCPRPC Service服務註冊健康檢查定義,並演示如何以標籤標識一個服務的多個實例。


歡迎關注技術公衆號: 零壹技術棧

零壹技術棧

本賬號將持續分享後端技術乾貨,包括虛擬機基礎,多線程編程,高性能框架,異步、緩存和消息中間件,分佈式和微服務,架構學習和進階等學習資料和文章。

相關文章
相關標籤/搜索