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

前言

近年微服務架構在互聯網應用領域中愈來愈火,引入微服務主要解決了單體應用

多個模塊的緊耦合無法擴展運維困難等問題。微服務架構就是按照功能粒度將業務模塊進行垂直拆分,對單體應用本身進行服務化組件化,每個組件單獨部署為小應用(從DB到UI)。微服務與微服務之間通過Service API進行交互,同時為了支持水平擴展性能提升服務可用性,單個服務允許同時部署一個或者多個服務實例。在運行時,每個實例通常是一個雲虛擬機或者Docker容器

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


正文

1. 服務發現與註冊

1.1. 具體流程

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

一個較為完整的服務註冊與發現流程如下:

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

1.2. 相關組件

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

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

1.3. 第三方實現

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

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

簡單對比:

與Zookeeper和etcd不一樣,Consul內嵌實現了服務發現系統,不需要構建自己的系統或使用第三方系統,客戶只需要註冊服務,並通過DNS或HTTP接口執行服務發現。

2. Consul和Registrator

2.1. Consul簡介

Consul是什麼

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

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

Consul的幾個概念

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

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

圖中包含兩個Consul數據中心,每個數據中心都是一個consul的集群。在數據中心1中,可以看出consul的集群是由N個SERVER,加上M個CLIENT組成的。而不管是SERVER還是CLIENT,都是consul集群的一個節點。所有的服務都可以註冊到這些節點上,正是通過這些節點實現服務註冊信息的共享。除了這兩個,還有一些小細節 一一 簡單介紹。

  • CLIENT

CLIENT表示consul的client模式,就是客戶端模式。是consul節點的一種模式,這種模式下,所有註冊到當前節點的服務會被轉發到SERVER節點,本身是不持久化這些信息。

  • SERVER

SERVER表示consul的server模式,表明這個consul是個server節點。這種模式下,功能和CLIENT都一樣,唯一不同的是,它會把所有的信息持久化的本地。這樣遇到故障,信息是可以被保留的。

  • SERVER-LEADER

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

  • 其它信息

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

2.2. Registrator簡介

什麼是Registrator

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

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

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

2.3. Docker安裝Consul集群

2.3.1. 集群節點規劃

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

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

Consul的配置參數信息說明:

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

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的日誌,追蹤運行情況:

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

現在集群中還沒有選舉leader節點,繼續啟動其餘兩臺Server節點node2和node3:

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節點的進程啟動日誌:

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

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節點的進程啟動日誌:

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

當3個Server節點都啟動並正常運行時,觀察node2和node3的進程日誌,可以發現node1被選舉為leader節點,也就是這個數據中心的Server Master。

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

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

觀察日誌發現,node2和node3都成功join到了node1所在的數據中心dc1。當集群中有3臺Consul Server啟動時,node1被選舉為dc1中的主節點。然後,node1會通過心跳檢查的方式,不斷地對node2和node3進行健康檢查。

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節點的進程啟動日誌:

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

可以發現:node4是以Client模式啟動運行的。啟動後完成後,把dc1數據中心中的以Server模式啟動的節點node1、node2和node3都添加到本地緩存列表中。當客戶端向node4發起服務發現的請求後,node4會通過RPC將請求轉發給Server節點中的其中一臺做處理。

2.4.5. 查看集群狀態

madison@ubuntu:~$ docker exec -t node1 consul members

dc1數據中心中的4個節點node1, node2, node3和node4分別成功啟動,Status表示他們的狀態,都為alive。node1, node2, node3以Server模式啟動,而node4以Client模式啟動。

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

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的容器進程啟動日誌:

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

Registrator在啟動過程完成了以下幾步操作:

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

2.5.3. 查看Consul的註冊狀態

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

服務註冊列表

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

NODES節點下掛載著dc1數據中心中的所有的Consul節點,包括Consul Server和Client。

通信節點列表

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

啟動Registrator以後,宿主機中的所有容器把服務都註冊到Consul的SERVICES上,測試完成!


總結

單數據中心的Consul集群的搭建就完成了!!!後續章節我會介紹如何使用Registrator進行服務註冊的

標籤化。然後通過docker部署多實例的Web容器來實現基於HTTP的RESTful Service和基於TCP的RPC Service的服務註冊健康檢查定義,並演示如何以標籤標識一個服務的多個實例。


分享到:


相關文章: