基於Docker的Consul集群實現服務發現

来源:https://www.cnblogs.com/wy123/archive/2019/12/27/12097157.html
-Advertisement-
Play Games

服務發現 其實簡單說,服務發現就是解耦服務與IP地址之間的硬綁定關係,以典型的集群為例,對於集群來說,是有多個節點的,這些節點對應多個IP(或者同一個IP的不同埠號),集群中不同節點責任是不一樣的。比如說一個數據集群中,可以分為讀節點或者寫節點,寫節點和讀節點都是相對的,不是硬綁定的,某一個邏輯節 ...


 

服務發現

其實簡單說,服務發現就是解耦服務與IP地址之間的硬綁定關係,
以典型的集群為例,對於集群來說,是有多個節點的,這些節點對應多個IP(或者同一個IP的不同埠號),集群中不同節點責任是不一樣的。
比如說一個數據集群中,可以分為讀節點或者寫節點,寫節點和讀節點都是相對的,不是硬綁定的,某一個邏輯節點,隨著故障轉移及恢復,是可以變換身份的(寫變讀,讀變寫;主降從,從升主等等)
集群對外提供服務的時候,對於外界來說,集群中節點身份變換的時候需要對外透明,外界無需因為集群節點的身份變換而更改配置,這就需要一個解耦合的服務。
Consul,zookeeper等中間件,就是做這個透明轉換的,也就是服務發現。這裡簡單測試consul作為服務發現的實現。 Consul是一種服務解耦解決方案(service mesh solution,糾結了好久不知道怎麼翻譯)提供具有服務發現配置和分段功能的全功能控制系統(control plane)
這些功能中的每一個都可以根據需要單獨使用也可以一起使用以構建完整的服務解耦 即便是用了谷歌翻譯的情況下,這段翻譯糾結了半天,不知道怎麼翻譯合適。

如下是按照自己對consul做服務發現的理解,簡單整理的邏輯結構圖,其原理還是比較容易理解的。
Consul is a service mesh solution providing a full featured control plane with service discovery, configuration, and segmentation functionality. Each of these features can be used individually as needed, or they can be used together to build a full service mesh. Consul requires a data plane and supports both a proxy and native integration model. Consul ships with a simple built-in proxy so that everything works out of the box, but also supports 3rd party proxy integrations such as Envoy. https://www.consul.io/intro/index.html 它提供如下幾個關鍵功能 服務發現   Consul的某些客戶端可以提供一個服務例如api或者mysql其它客戶端可以使用Consul去發現這個服務的提供者   使用DNS或者HTTP應用可以很容易的找到他們所依賴的服務 健康檢查
  Consul客戶端可以提供一些健康檢查這些健康檢查可以關聯到一個指定的服務服務是否返回200 OK),也可以關聯到本地節點記憶體使用率是否在90%以下)。
  這些信息可以被一個操作員用來監控集群的健康狀態被服務發現組件路由時用來遠離不健康的主機 鍵值存儲 
  應用可以使用Consul提供的分層鍵值存儲用於一些目的包括動態配置特征標記協作leader選舉等等通過一個簡單的HTTP API可以很容易的使用這個組件
多數據中心 
  Consul對多數據中心有非常好的支持這意味著Consul用戶不必擔心由於創建更多抽象層而產生的多個區域
Consul被設計為對DevOps群體和應用開發者友好他非常適合現代的可伸縮的基礎設施     本文基於docker來實現consul的服務發現配置,方法consul agent是通過json註冊的模式實現服務註冊,
其中consul的服務端是3節點的集群,客戶點是6節點3主3從的redis伺服器集群,consul實現redis集群中讀寫服務註冊於發現。

儘管Redis cluster有多IP方式驅動連接,這裡僅僅為了測試“服務發現”的。
其實本來想測試MySQL單主模式的MGR,實現讀寫分離的服務發現,但是MySQL有點太重了,機器配置不夠,所以做了Redis的集群來測試服務發現
    consul服務端集群安裝配置
作為服務發現的載體,consul是可以使用單節點運行的,作為解析服務的載體,是一個非常重要的角色,集群化具有更強的抗災性,因此更多的時候是以多節點集群的方式運行解析服務的這個載體。

這裡使用三個節點作為consul的集群服務端來運行,三個consul的服務節點IP分別是:172.18.0.11 ,172.18.0.12,172.18.0.13,需要固定IP docker network create --subnet=172.18.0.11/16 mynetwork  docker run -itd --name consul01 --net mynetwork --ip 172.18.0.11 -v /usr/local/docker_file/consul01/:/usr/local/ centos   docker run -itd --name consul02 --net mynetwork --ip 172.18.0.12 -v /usr/local/docker_file/consul02/:/usr/local/ centos   docker run -itd --name consul03 --net mynetwork --ip 172.18.0.13 -v /usr/local/docker_file/consul03/:/usr/local/ centos   分別在每個容器中創建consul服務(unzip consul_1.6.2_linux_amd64.zip解壓縮即可,非常簡單) 三個容器節點的server.json節點配置文件如下,唯一的區別就是bind_addr指定為當前節點的IP
如下是172.18.0.11節點的配置,不同節點僅需修改bind_addr為對應機器(容器)的IP

/usr/local/server.json 
{
    "datacenter": "dc1",
    "data_dir": "/usr/local/",
    "log_level": "INFO",
    "server": true,
    "bootstrap_expect": 3,
    "bind_addr": "172.18.0.11",
    "client_addr": "0.0.0.0",
    "start_join": ["172.18.0.11","172.18.0.12","172.18.0.13"],
    "ui":true
}
依次登錄三個容器中,以server模式啟動consul服務
./consul agent -server -config-dir=/usr/local > /usr/local/consul.log &
由於配置文件中制定了集群的IP列表,因此無需顯式加入集群(cluster join),正常情況下,啟動三個節點後,會自動組成一個集群,並且自動選舉出來一個leader。 consul 集群服務的狀態 ./consul members --http-addr 172.18.0.11:8500 ./consul operator raft list-peers -http-addr=172.18.0.12:8500

consul客戶端安裝配置 容器客戶端節點安裝,6個節點IP分別是:172.18.0.21,172.18.0.22,172.18.0.23,172.18.0.24,172.18.0.25,172.18.0.26
docker run -itd --name redis01 --net mynetwork --ip 172.18.0.21 -v /usr/local/docker_file/redis01/:/usr/local/ centos 
docker run -itd --name redis02 --net mynetwork --ip 172.18.0.22 -v /usr/local/docker_file/redis02/:/usr/local/ centos 
docker run -itd --name redis03 --net mynetwork --ip 172.18.0.23 -v /usr/local/docker_file/redis03/:/usr/local/ centos 
docker run -itd --name redis04 --net mynetwork --ip 172.18.0.24 -v /usr/local/docker_file/redis04/:/usr/local/ centos 
docker run -itd --name redis05 --net mynetwork --ip 172.18.0.25 -v /usr/local/docker_file/redis05/:/usr/local/ centos 
docker run -itd --name redis06 --net mynetwork --ip 172.18.0.26 -v /usr/local/docker_file/redis06/:/usr/local/ centos
  6個client節點的配置以及服務定義,服務探測腳本如下
如下是172.18.0.21節點的配置,不同節點僅需修改bind_addr為對應機器(容器)的IP

client.json
{
  "data_dir": "usr/local/consuldata",
  "enable_script_checks": true,
  "bind_addr": "172.18.0.21",
  "retry_join": ["172.18.0.11","172.18.0.12","172.18.0.13"],
  "retry_interval": "30s",
  "rejoin_after_leave": true,
  "start_join": ["172.18.0.11","172.18.0.12","172.18.0.13"]
}
分別啟動三個client節點的consul服務,以client的模式運行,啟動後,正常情況下會自動加入到consul的服務端集群中。 ./consul agent -config-dir=/usr/local/consuldata > /usr/local/consuldata/consul.log & ./consul members --http-addr 172.18.0.11:8500     consul客戶端代理服務註冊
6個容器節點依次安裝redis,做成一個集群(步驟略),這裡的consul客戶端代理的是一個3中3從的Redis集群,這裡不列出來Redis集群的安裝。
Redis集群安裝參考https://www.cnblogs.com/wy123/p/12012848.html,還是非常方便的,在本地(容器節點)一鍵創建6個節點3主3從的集群。
其中主節點是172.18.0.21,172.18.0.22,172.18.0.23,從節點是172.18.0.24,172.18.0.25,172.18.0.26

這裡是使用 w-master-redis-8888.service.consul名字作為三個redis集群節點的服務代理。
172.18.0.21節點上的redis-master-8888.json(172.18.0.22,172.18.0.23,172.18.0.24,172.18.0.25,172.18.0.26 類同,僅需修改address)
{
  "services": 
  [
    {
      "name": "w-master-redis-8888",
      "tags": [
        "master"
      ],
      "address": "172.18.0.21",
      "port": 8888,
      "checks": [
        {
         "args":["sh","-c","/usr/local/consuldata/check_redis_master.sh 172.18.0.21 8888 ******"],
         "Shell":"/bin/bash",
         "interval": "15s"
        }
      ]
    }
  ]
}

redis-slave-8888.json 

{
  "services": 
  [
    {
      "name": "r-slave-redis-8888",
      "tags": [
        "master"
      ],
      "address": "172.18.0.21",
      "port": 8888,
      "checks": [
        {
         "args":["sh","-c","/usr/local/consuldata/check_redis_slave.sh 172.18.0.21 8888 ******"],
         "Shell":"/bin/bash",
         "interval": "15s"
        }
      ]
    }
  ]
}

Consul client節點的Redis主節點(寫節點)服務檢查腳本check_redis_master.sh
以下腳本來源於https://www.cnblogs.com/gomysql/p/8010552.html,做了簡單的修改,在節點的身份判斷邏輯上需要加強。

#!/bin/bash
host=$1
myport=$2
auth=$3
if [ ! -n "$auth" ]
then
auth='\"\"'
fi
comm="/usr/local/redis_instance/redis8888/bin/redis-cli -h $host -p $myport -a $auth " 
role=`echo 'INFO Replication'|$comm |grep -Ec 'role:master'`
echo 'INFO Replication'|$comm
if [ $role -ne 1 ]
then
    exit 2
fi

Consul client節點的Redis從節點服務檢查腳本check_redis_slave.sh

#!/bin/bash
host=$1
myport=$2
auth=$3
if [ ! -n "$auth" ]
then
auth='\"\"'
fi
comm="/usr/local/redis_instance/redis8888/bin/redis-cli -h $host -p $myport -a $auth "
role=`echo 'INFO Replication'|$comm |grep -Ec 'role:slave'`
echo $role
echo 'INFO Replication'|$comm


if [ $role -ne 1 ]
then
    exit 2
fi

 

Consul服務發現

redis集群配置成功後,重新載入代理服務,consul reload,一切正常的話,consul服務端就可以解析配置的服務了。
如下註冊了兩個服務,分別是r-slave-redis-8888,w-master-redis-8888,分別代表Redis集群的讀寫節點。

可以看到,成功地解析了 w-master-redis-8888.service.consul這個服務,映射到172.18.0.21,172.18.0.22,172.18.0.23三個節點。
需要註意的是,這三個節點都是寫節點,這裡僅僅是為了實現服務發現(儘管redis 有多IP的驅動支持)

r-slave-redis-8888.service.consul服務的解析,指向了三個從節點,172.18.0.24,172.18.0.25,172.18.0.26

故障轉移之後的服務發現:模擬主節點故障,對172.18.0.21節點手動故障轉移,現在172.18.0.21與172.18.0.24角色交換

Redis集群故障轉以後的服務發現解析結果 對於w-master-redis-8888.service.consul這個服務,成功解析到172.18.0.24,172.18.0.22,172.18.0.23三個主節點

Redis集群故障轉以後的服務發現解析結果 對於w-master-redis-8888.service.consul這個服務,成功解析到172.18.0.24,172.18.0.22,172.18.0.23三個主節點

 

遇到的問題:
1,cosnul服務端集群的時候,clustercenter一開始自定義了一個名稱myconsule_datacenter,導致client節點死活加不進來,按照預設的dc1就沒有問題
目前還不理解這個datacenter的命名規則是什麼?
2,容器節點中的shell腳本要授予可執行許可權chmod +x check_XXX.sh
3,其他異常問題,一定要看日誌,搜索一下基本上都有結果。
以下純粹是Redis集群的問題,與Consul沒有直接關係,僅作為本測試中遇到的問題。
4,容器節點的Redis集群時,需要移除bind_ip的127.0.0.1節點,直接配置docker創建容器時候的IP,創建集群的時候會一致等待,waiting for the cluster to join
這一點redis-cli --cluster做的很扯淡,明明找不到節點,還要死等,不人為終止的話,他會一直waiting
5,Redis集群時候,因為主從都是相對的,需要相互識別對方,主從節點都要指定“masterauth”和“requirepass”,且密碼一致,否則執行cluster  failover提示成功,但故障轉移不成功
6,遇到一個靈異的問題(之前單機多實例的時候也遇到過),在啟動容器上的Redis服務的時候,如果使用絕對路徑啟動,在創建集群的時候會出現從節點無法添加到集群中去的情況,停止服務,以相對路徑方式重啟之後就沒有這個問題


總的來說consul這個中間件使用起來還算是比較簡單,配置也很清爽,不像某些中間件令人作嘔的配置結構(mycat???)
這裡沒有配置多數據中心模式,僅配置了單數據中心模式,作為一款服務發現的中間件,是完全沒有問題的,尤其是作為MySQL集群不支持多IP連接驅動的資料庫連接。


參考:

https://www.cnblogs.com/gomysql/p/8010552.html
https://blog.csdn.net/jeffscott/article/details/88888708 https://www.cnblogs.com/duanxz/p/10564502.html https://www.cnblogs.com/gomysql/p/8010552.html https://segmentfault.com/a/1190000016677665 https://blog.csdn.net/liuzhuchen/article/details/81913562
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. MySQL架構 1.1 邏輯架構圖 1.1.1 Connection Pool: 連接池 * 管理緩衝用戶連接,線程處理等需要緩存的需求。 * 負責監聽對 MySQL Server 的各種請求,接收連接請求,轉發所有連接請求到線程管理模塊。每一個連接上 MySQL Server 的客戶端請求都 ...
  • 一、基本概念 假設用戶A要從他的賬戶裡面給B轉賬1000元,那麼就需要兩步來實現,首先從A的賬號減去1000元,再給B賬號加1000元。這兩個步驟中,任何一步都不能少或者出錯,這兩步要麼都得到成功操作完成,要麼什麼都不做,中途出錯也要回滾到轉賬開始之前的狀態。這樣的一個過程就是我們經常說的事務。根據 ...
  • 官網:http://automapper.org/ 源碼:https://github.com/AutoMapper/AutoMapper NUGET安裝: PM> Install-Package AutoMapper AutoMapper是基於對象到對象約定的映射工具,常用於(但並不僅限制於)把復 ...
  • Redis持久化 官方文檔: https://redis.io/topics/persistence Redis用戶認證 redis預設開啟了保護模式,只允許本地迴環地址登錄並訪問資料庫 禁止protected mode protected mode yes/no (保護模式,是否只允許本地訪問) ...
  • 使用sp_MSForEachTable這個系統存儲過程。 創建一張臨時表,它有2個欄位,[Table_Name]和[Total_Records]。 然後使用sp_MSForEachTable來處理,把結果插入上面創建的臨時表中。如果Total_Records為0的,說明此表沒有任何記錄。 DROP ...
  • 問題描述: 今天程式那邊說測試服裡面有兩個項目,為了數據不衝突,想一臺伺服器搞兩個Redis實例, 然後自己這邊查詢了一下,確實可以這麼整,只需要區分埠號和區分配置文件方面就行, 原理與nginx和tomcat等添加容器單實例多應用應該差不多,做個筆記記錄一下。 1、複製新的配置文件,改變配置名稱 ...
  • 從下麵2句SQL語句執行來看, SELECT * FROM sys.tables WHERE OBJECTPROPERTY(OBJECT_ID,'TableHasPrimaryKey') <> 0 SELECT * FROM sys.tables WHERE OBJECTPROPERTY(OBJEC ...
  • 如標題所言,需要把2列的數據進行對調,列1的值存入列2,把列2的值存儲列1中去。 如何實現,2種方法: 第1種,對列名進行修改,把name1改為name2,把name2改為name1即可: sp_rename 'Q3.name1',temp_name1,'column' GO sp_rename ' ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...