使用 Consul 做爲 Python 微服務的配置中心

半部分主要爲 Consul 的一些介紹,若已經瞭解 Consul,能夠直接跳轉到:html

使用 Consul 做爲 Python 微服務的配置中心python

Consul 簡單介紹

Consul 是 HashiCorp 公司推出的開源工具,用於實現分佈式系統的服務發現與配置。Consul 是分佈式的、高可用的、 可橫向擴展的。它具有如下特性:linux

  • 服務發現: Consul 提供了經過 DNS 或者 HTTP 接口的方式來註冊服務和發現服務。一些外部的服務經過 Consul 很容易的找到它所依賴的服務。
  • 健康檢測: Consul 的 Client 提供了健康檢查的機制,能夠經過用來避免流量被轉發到有故障的服務上。
  • Key/Value 存儲: 應用程序能夠根據本身的須要使用 Consul 提供的 Key/Value 存儲。 Consul 提供了簡單易用的 HTTP 接口,結合其餘工具能夠實現動態配置、功能標記、領袖選舉等等功能。
  • 多數據中心: Consul 支持開箱即用的多數據中心. 這意味着用戶不須要擔憂須要創建額外的抽象層讓業務擴展到多個區域。

 

 

Consul 架構圖解

Consul 集羣間使用了 Gossip 協議通訊和 raft 一致性算法。上面這張圖涉及到了不少術語:nginx

  • Gossip —— Gossip protocol 也叫 Epidemic Protocol (流行病協議),實際上它還有不少別名,好比:「流言算法」、「疫情傳播算法」等。 這個協議的做用就像其名字表示的意思同樣,很是容易理解,它的方式其實在咱們平常生活中也很常見,好比電腦病毒的傳播,森林大火,細胞擴散等等。
  • Client —— 一個 Client 是一個轉發全部 RPC 到 server 的代理。這個 client 是相對無狀態的。client 惟一執行的後臺活動是加入 LAN gossip 池。這有一個最低的資源開銷而且僅消耗少許的網絡帶寬。
  • Server —— 一個 server 是一個有一組擴展功能的代理,這些功能包括參與 Raft 選舉,維護集羣狀態,響應 RPC 查詢,與其餘數據中心交互 WAN gossip 和轉發查詢給 leader 或者遠程數據中心。
  • DataCenter —— 雖然數據中心的定義是顯而易見的,可是有一些細微的細節必須考慮。例如,在 EC2 中,多個可用區域被認爲組成一個數據中心。咱們定義數據中心爲一個私有的,低延遲和高帶寬的一個網絡環境。這不包括訪問公共網絡,可是對於咱們而言,同一個 EC2 中的多個可用區域能夠被認爲是一個數據中心的一部分。
  • Consensus —— 一致性,使用 Consensus 來代表就 leader 選舉和事務的順序達成一致。爲了以容錯方式達成一致,通常有超過半數一致則能夠認爲總體一致。Consul 使用 Raft 實現一致性,進行 leader 選舉,在 consul 中的使用 bootstrap 時,能夠進行自選,其餘 server 加入進來後 bootstrap 就能夠取消。
  • LAN Gossip —— 它包含全部位於同一個局域網或者數據中心的全部節點。
  • WAN Gossip —— 它只包含 Server。這些 server 主要分佈在不一樣的數據中心而且一般經過因特網或者廣域網通訊。
  • RPC——遠程過程調用。這是一個容許 client 請求 server 的請求/響應機制。

Gossip 介紹

這裏先簡單介紹一下 Gossip 協議的執行過程:git

Gossip 過程是由種子節點發起,當一個種子節點有狀態須要更新到網絡中的其餘節點時,它會隨機的選擇周圍幾個節點散播消息,收到消息的節點也會重複該過程,直至最終網絡中全部的節點都收到了消息。這個過程可能須要必定的時間,因爲不能保證某個時刻全部節點都收到消息,可是理論上最終全部節點都會收到消息,所以它是一個最終一致性協議。github

如今,咱們經過一個具體的實例來深刻體會一下 Gossip 傳播的完整過程: 爲了表述清楚,咱們先作一些前提設定 一、Gossip 是週期性的散播消息,把週期限定爲 1 秒 二、被感染節點隨機選擇 k 個鄰接節點(fan-out)散播消息,這裏把 fan-out 設置爲 3,每次最多往 3 個節點散播。 三、每次散播消息都選擇還沒有發送過的節點進行散播 四、收到消息的節點再也不往發送節點散播,好比 A -> B,那麼 B 進行散播的時候,再也不發給 A。 這裏一共有 16 個節點,節點 1 爲初始被感染節點,經過 Gossip 過程,最終全部節點都被感染:web

 

 

注意要點:算法

  • Consul Cluster 由部署和運行了 Consul Agent 的節點組成。在 Cluster 中有兩種角色:Server 和 Client。
  • Server 和 Client 的角色和 Consul Cluster 上運行的應用服務無關, 是基於 Consul 層面的一種角色劃分.
  • Consul Server: 用於維護 Consul Cluster 的狀態信息。 官方建議是: 至少要運行 3 個或者 3 個以上的 Consul Server。 多個 server 之中須要選舉一個 leader, 這個選舉過程 Consul 基於 Raft 協議實現. 多個 Server 節點上的 Consul 數據信息保持強一致性。在局域網內與本地客戶端通信,經過廣域網與其餘數據中心通信。
  • Consul Client: 只維護自身的狀態, 並將 HTTP 和 DNS 接口請求轉發給服務端。

Consul 與其餘常見服務發現框架對比

名稱 優勢 缺點 接口 一致性算法
zookeeper 1.功能強大,不只僅只是服務發現
2.提供 watcher 機制能實時獲取服務提供者的狀態
3.dubbo 等框架支持
1.沒有健康檢查
2.需在服務中集成 sdk,複雜度高
3.不支持多數據中心
sdk Paxos
consul 1.簡單易用,不須要集成 sdk
2.自帶健康檢查
3.支持多數據中心
4.提供 web 管理界面
1.不能實時獲取服務信息的變化通知 http/dns Raft
etcd 1.簡單易用,不須要集成 sdk
2.可配置性強
1.沒有健康檢查
2.需配合第三方工具一塊兒完成服務發現
3.不支持多數據中心
http Raft

Consul 單機環境部署

首先 clone 本項目到本地:docker

  1.  
    $ git clone git@github.com:elfgzp/python-consul-demo.git
  2.  
    複製代碼

Consul 單機部署所須要用到的文件以下:bootstrap

  • docker-compose-server.yml —— Consul Server docker-compose 配置文件
  • docker-compose-client.yml —— Consul Client docker-compose 配置文件

能夠看到兩個 docker-compose 文件均暴露了 8 個端口。根據官方文檔,這些端口的做用以下:

Ports Used

Consul requires up to 6 different ports to work properly, some on TCP, UDP, or both protocols. Below we document the requirements for each port.

  • Server RPC (Default 8300). This is used by servers to handle incoming requests from other agents. TCP only.
  • Serf LAN (Default 8301). This is used to handle gossip in the LAN. Required by all agents. TCP and UDP.
  • Serf WAN (Default 8302). This is used by servers to gossip over the WAN, to other servers. TCP and UDP. As of Consul 0.8 the WAN join flooding feature requires the Serf WAN port (TCP/UDP) to be listening on both WAN and LAN interfaces. See also: Consul 0.8.0 CHANGELOG and GH-3058
  • HTTP API (Default 8500). This is used by clients to talk to the HTTP API. TCP only.
  • DNS Interface (Default 8600). Used to resolve DNS queries. TCP and UDP.

還有一些配置參數這裏就不一一介紹了,官方文檔寫的很是詳細。

Consul Server 部署

首先須要給環境變量 CONSUL_SERVER_IP_ADDR 賦值,若爲 ECS 則爲 ECS 的外網 IP,這裏也是演示在 ECS 部署。

  1.  
    $ export CONSUL_SERVER_IP_ADDR={YOUR_IP_ADDR}
  2.  
    複製代碼

而後運行,這裏沒有使用 -d 參數,方便查看日誌:

  1.  
    $ docker-compose -f docker-compose-server.yml up
  2.  
    複製代碼

 

 

Consul Client 部署

運行 docker-compose 前,設置 CONSUL_SERVER_HOST 環境變量:

  1.  
    $ export CONSUL_SERVER_HOST={YOUR_SERVER_HOST}
  2.  
    複製代碼

而後運行:

  1.  
    $ docker-compose -f docker-compose-client.yml up
  2.  
    複製代碼

 

 

部署完成後能夠經過 Consul UI 的 Nodes 看到兩個 Healthy Nodes

 

 

也能夠在部署好 Consul Client 的宿主機上運行:

  1.  
    $ consul members
  2.  
    複製代碼

 

 

這裏要注意:

在查看了 Consul 倉庫的 issue#1720 發現,Consul 提供的 Web UI 並無提供 Auth 功能,因此可能要依靠第三方服務來實現,評論中也有提到:

highlyunavailable commented on 17 Feb 2016

When I ran a Consul Web UI I just used nginx and github.com/bitly/oauth… to provide authentication.

可是 HTTP 接口的權限,能夠經過 Consul ACL 來控制,這是後話。

使用 Consul 做爲 Python 微服務的配置中心

Consul 做爲數據中心,提供了 k/v 存儲的功能,咱們能夠利用這個功能爲 Python 微服務提供配置中心。

Consul 提供了 HTTP 接口,咱們能夠從他的接口獲取數據,固然咱們不用本身去實現,python-consul 已經幫咱們造好了輪子。

並且官方文檔很是貼心,已經貼好了 Python 經常使用框架的一些 demo 代碼:

  1.  
    from tornado.ioloop import IOLoop
  2.  
    from tornado.gen import coroutine
  3.  
    from consul.base import Timeout
  4.  
    from consul.tornado import Consul
  5.  
     
  6.  
     
  7.  
    class Config(object):
  8.  
    def __init__(self, loop):
  9.  
    self.foo = None
  10.  
    loop.add_callback(self.watch)
  11.  
     
  12.  
    @coroutine
  13.  
    def watch(self):
  14.  
    c = Consul()
  15.  
     
  16.  
    # asynchronously poll for updates
  17.  
    index = None
  18.  
    while True:
  19.  
    try:
  20.  
    index, data = yield c.kv.get('foo', index=index)
  21.  
    if data is not None:
  22.  
    self.foo = data[ 'Value']
  23.  
    except Timeout:
  24.  
    # gracefully handle request timeout
  25.  
    pass
  26.  
     
  27.  
    if __name__ == '__main__':
  28.  
    loop = IOLoop.instance()
  29.  
    _ = Config(loop)
  30.  
    loop.start()
  31.  
    複製代碼

結合 consul-template 用解藕的方式去配置微服務

Consul Template 提供一個方便的方式從 Consul 獲取數據經過 consul-template 的後臺程序保存到文件系統。
這個後臺進程監控 Consul 示例的變化並更新任意數量的模板到文件系統.做爲一個附件功能,模板更新完成後 consul-template 能夠運行任何命令.能夠查看示例部分看這個功能將會對哪些應用場景產生幫助。

首先須要在 Consul Client 所在的宿主機安裝 consul-template,因爲 Demo 宿主機環境爲 Mac OS,因此能夠直接用 HomeBrew 進行安裝。

  1.  
    $ brew install consul-template
  2.  
    複製代碼

安裝完成後進入倉庫的 python-web-service 路徑,這是一個用 tornado 寫的簡單的 Web 服務。執行以下命令:

  1.  
    $ cd python-web-service && docker-compose up -d
  2.  
    複製代碼

等待命令運行完成,服務啓動後,訪問 localhost:8888 能夠看到返回內容:

  1.  
    $ curl http://localhost:8888
  2.  
    Hello World
  3.  
    複製代碼

而後咱們回到倉庫路徑,進入 consul-template 目錄,該目錄主要包含如下兩個文件:

  1.  
    $ cd ../consul-template
  2.  
    $ tree
  3.  
    .
  4.  
    ├── config.hcl # consul-template 配置文件
  5.  
    └── config.py.ctmpl # python-web-service 配置模版文件
  6.  
    複製代碼

查看一下 config.hcl 文件的內容:

  1.  
    consul {
  2.  
    address = "127.0.0.1:8500"
  3.  
     
  4.  
    }
  5.  
     
  6.  
    template {
  7.  
     
  8.  
    source = "./config.py.ctmpl"
  9.  
    destination = "../python-web-service/config.py"
  10.  
    command = "docker restart python-web-service_python-web-service_1"
  11.  
     
  12.  
    }
  13.  
    複製代碼

先介紹一下 *.hcl 配置文件,這個是 Consul 中很是常見的配置文件格式,也是 HashiCorp 下的產品所用的主要配置文件格式。配置文件中包含了 4 個重要的參數:

  • address —— Consul Client 的訪問地址和端口
  • source —— 須要配置的服務的配置文件模板
  • destination —— 配置文件渲染後輸出的路徑
  • command —— 當配置變動後,須要執行的命令

再來看看模板文件 config.py.ctmpl

  1.  
    # -*- coding: utf-8 -*-
  2.  
    __author__ = 'gzp'
  3.  
     
  4.  
    GREETING = '{{ keyOrDefault "python-web-service/greeting" "Hello World" }}'
  5.  
    複製代碼

模版文件的格式很是相似 Jinja2 的語法,這裏的意思獲取 key 爲 python-web-service/greeting 下的值,默認值爲 HelloWorld

接下來運行命令使 consul-template 生效:

  1.  
    $ consul-template -config config.hcl
  2.  
    複製代碼

咱們能夠訪問 Consul Web UI 的 Key/Value 來修改咱們的值:

 

 

將 Hello World 修改成 Hello Consul,配置可能沒有當即生效,若看到 consul-template 輸出,則表明配置生效,服務以及重啓:

  1.  
    $ consul-template -config config.hcl
  2.  
    python-web-service_python-web-service_1
  3.  
    複製代碼

而後再次訪問一下 web 服務:

  1.  
    $ curl http://localhost:8888
  2.  
    Hello Consul
  3.  
    複製代碼

能夠看到配置已經生效。

參考文獻

Consul 入門 - 運維之美

P2P 網絡核心技術:Gossip 協議

服務發現框架選型,Consul 仍是 Zookeeper 仍是 etcd

相關文章
相關標籤/搜索