SpringCloud學習總結(七)——服務注冊中心Consul


案例准備

用例spring_cloud_consul 項目地址:傳送門

 

Eureka替換方案Consul

 

一、Eureka閉源影響

 

 

 

在Euraka的GitHub上,宣布Eureka 2.x閉源。近這意味着如果開發者繼續使用作為 2.x 分支上現有工作 repo 一部分發布的代碼庫和工件,則將自負風險。

Eureka的替換方案

Zookeeper

ZooKeeper是一個分布式的,開放源碼的分布式應用程序協調服務,是Google的Chubby一個開源的實現,是Hadoop和Hbase的重要組件。它是一個為分布式應用提供一致性服務的軟件,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。

Consul consul是近幾年比較流行的服務發現工具,工作中用到,簡單了解一下。consul的三個主要應用場景:服務發現、服務隔離、服務配置。

Nacos Nacos 是阿里巴巴推出來的一個新開源項目,這是一個更易於構建雲原生應用的動態服務發現、配置管理和服務管理平台。Nacos 致力於幫助您發現、配置和管理微服務。Nacos 提供了一組簡單易用的特性集,幫助您快速實現動態服務發現、服務配置、服務元數據及流量管理。Nacos 幫助您更敏捷和容易地構建、交付和管理微服務平台。 Nacos 是構建以“服務”為中心的現代應用架構 (例如微服務范式、雲原生范式) 的服務基礎設施。

 

二、什么是consul

consul 概述

consul官網

 

 

 

Consul 是 HashiCorp 公司推出的開源工具,用於實現分布式系統的服務發現與配置。與其它分布式服務注冊與發現的方案,Consul 的方案更“一站式”,內置了服務注冊與發現框 架、分布一致性協議實現、健康檢查、Key/Value 存儲、多數據中心方案,不再需要依賴其它工具(比如 ZooKeeper 等)。使用起來也較 為簡單。Consul 使用 Go 語言編寫,因此具有天然可移植性(支持Linux、windows和Mac OS X);安裝包僅包含一個可執行文件,方便部署,與 Docker 等輕量級容器可無縫配合。

Consul 的優勢:

  • 使用 Raft 算法來保證一致性, 比復雜的 Paxos 算法更直接. 相比較而言, zookeeper 采用的是Paxos, 而 etcd 使用的則是 Raft。

  • 支持多數據中心,內外網的服務采用不同的端口進行監聽。 多數據中心集群可以避免單數據中心的單點故障,而其部署則需要考慮網絡延遲, 分片等情況等。 zookeeper 和 etcd 均不提供多數據中心功能的支持。

  • 支持健康檢查。 etcd 不提供此功能。

  • 支持 http 和 dns 協議接口。 zookeeper 的集成較為復雜, etcd 只支持 http 協議。

  • 官方提供 web 管理界面, etcd 無此功能。

  • 綜合比較, Consul 作為服務注冊和配置管理的新星, 比較值得關注和研究。

特性:

  • 服務發現

  • 健康檢查

  • Key/Value 存儲

  • 多數據中心

 

consul與Eureka的區別

(1)一致性

Consul強一致性(CP)

  • 服務注冊相比Eureka會稍慢一些。因為Consul的raft協議要求必須過半數的Consul節點都寫入成功才認為注冊成功

  • Leader掛掉時,重新選舉期間整個consul不可用。保證了強一致性但犧牲了可用性。

Eureka保證高可用和最終一致性(AP)

  • 服務注冊相對要快,因為不需要等注冊信息replicate到其他節點,也不保證注冊信息是否replicate成功

  • 當數據出現不一致時,雖然Eureka節點 A, B上的注冊信息不完全相同,但每個Eureka節點依然能夠正常對外提供服務,這會出現查詢服務信息時如果請求A查不到,但請求B就能查到。如此保證了可用性但犧牲了一致性。

(2)開發語言和使用

  • eureka就是個servlet程序,跑在servlet容器中

  • Consul則是go編寫而成,安裝啟動即可

 

consul的下載與安裝

Consul 不同於 Eureka 需要單獨安裝,訪問 Consul 官網下載 Consul 的最新版本,我這里是consul1.5x。根據不同的系統類型選擇不同的安裝包,從下圖也可以看出 Consul 支持所有主流系統。

 

 

 

 

1、安裝consul

將下載的解壓包保存在linux虛擬中,解壓到指定目錄中

#解壓zip壓縮包,到/usr/local/server/consul目錄
unzip consul_1.5.3_linux_amd64.zip -d /usr/local/server/consul
##測試一下
./consul

 

2、啟動consul服務

#進入目錄/usr/local/server/consul 輸入consul
./consul agent -dev -client=0.0.0.0
​
# -dev      參數表示開發
# -ui       參數表示打開ui,否則看不到ui界面。
# -node     參數表示給這個節點增加一個名稱
# -client   參數表示綁定 ip 0.0.0.0,表示外部地址都可訪問

 

 

 

 

啟動成功之后訪問: http://192.168.126.99:8500/ui/dc1/services ,可以看到 Consul 的管理界面

 

 

 

 

三、consul的基本使用

Consul 支持健康檢查,並提供了 HTTP 和 DNS 調用的API接口完成服務注冊,服務發現,以及K/V存儲這些功能。接下來通過發送HTTP請求的形式來了解一下Consul

1、服務注冊與發現

(1)注冊服務

通過postman發送put請求到 http://192.168.126.99:8500/v1/catalog/register地址可以完成服務注冊

{
    "Datacenter": "dc1",
    "Node": "node01",
    "Address": "192.168.74.102",
    "Service": {
        "ID":"mysql-01",
        "Service": "mysql",
        "tags": ["master","v1"],
        "Address": "192.168.74.102",
        "Port": 3306
        }
}

 



 

 

 

 

(2)服務查詢

通過postman發送get請求到 http://192.168.126.99:8500/v1/catalog/services查看所有的服務列表

 

 

 

通過postman發送get請求http://192.168.126.99:8500/v1/catalog/service/ +服務名 查看具體的服務詳情

 

 

 

(3)服務刪除

通過postman發送put請求到http://192.168.126.99:8500/v1/catalog/deregister刪除服務

{
    "Datacenter": "dc1",
    "Node": "node01",
    "ServiceID": "mysql-01"
}

 

 

 

 

 

 

2、Consul的KV存儲

可以參照Consul提供的KV存儲的 API完成基於Consul的數據存儲

含義 請求路徑 請求方式
查看key v1/kv/:key GET
保存或更新 v1/kv/:key put
刪除 /v1/kv/:key DELETE

 

  • key值中可以帶/, 可以看做是不同的目錄結構。

  • value的值經過了base64_encode,獲取到數據后base64_decode才能獲取到原始值。數據不能大於512Kb

  • 不同數據中心的kv存儲系統是獨立的,使用dc=?參數指定。

四、項目引入consul的服務注冊

(1)案例准備


 

 

 

 

(2)修改微服務的相關pom文件

修改商品、訂單服務的pom文件,添加SpringCloud提供的基於Consul的依賴

 <!--SpringCloud提供的基於Consul的服務發現-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-consul-discovery</artifactId>
    </dependency>
<!--actuator用於心跳檢查-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>

 

其中 spring-cloud-starter-consul-discovery 是SpringCloud提供的對consul支持的相關依賴。 spring-boot-starter-actuator 適用於完成心跳檢測響應的相關依賴。

 

(3)修改application配置文件

修改商品、訂單服務的application.yml配置文件,添加consul服務發現的相關配置信息

###開始配置consul的服務注冊
cloud:
  consul:
    host: 192.168.126.99 #consul服務器的主機地址
    port: 8500 #consul服務器的ip地址
    discovery:
      #是否需要注冊
      register: true
      #注冊的實例ID (唯一標志)
      instance-id: ${spring.application.name}-1
      #服務的名稱
      service-name: ${spring.application.name}
      #服務的請求端口
      port: ${server.port}
      #指定開啟ip地址注冊
      prefer-ip-address: true
      #當前服務的請求ip
      ip-address: ${spring.cloud.client.ip-address}

 

其中 spring.cloud.consul 中添加consul的相關配置

  • host:表示Consul的Server的請求地址

  • port:表示Consul的Server的端口

  • discovery:服務注冊與發現的相關配置

    • instance-id : 實例的唯一id(推薦必填),spring cloud官網文檔的推薦,為了保證生成一個唯一的id ,也可以換成${spring.application.name}:${spring.cloud.client.ipAddress}

    • prefer-ip-address:開啟ip地址注冊

    • ip-address:當前微服務的請求ip

(4)修改訂單服務主項目類

修改OrderApplication類,添加Ribbon負載均衡的注解;springcloud對consul進行了進一步的處理,向其中集成了ribbon的支持

###開始配置consul的服務注冊
cloud:
  consul:
    host: 192.168.126.99 #consul服務器的主機地址
    port: 8500 #consul服務器的ip地址
    discovery:
      #是否需要注冊
      register: true
      #注冊的實例ID (唯一標志)
      instance-id: ${spring.application.name}-1
      #服務的名稱
      service-name: ${spring.application.name}
      #服務的請求端口
      port: ${server.port}
      #指定開啟ip地址注冊
      prefer-ip-address: true
      #當前服務的請求ip
      ip-address: ${spring.cloud.client.ip-address}

 

 

(5)修改OrderController類,使用負載均衡策略調用。

@RestController
@RequestMapping("/order")
public class OrderController {//注入restTemplate對象
    @Autowired
    private RestTemplate restTemplate;
​
    @RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
    public Product findById(@PathVariable Long id) {
        //Ribbon負載均衡調用
        Product product = restTemplate.getForObject("http://service-product/product/"+id,Product.class);;
        //Product product = restTemplate.getForObject("http://localhost:9001/product/"+id,Product.class);
        return product;
    }
​
}

 

 

(6)在控制台中查看服務列表

 

 

 

 

五、consul高可用集群

 

 

 

此圖是官網提供的一個事例系統圖,圖中的Server是consul服務端高可用集群,Client是consul客戶端。consul客戶端不保存數據,客戶端將接收到的請求轉發給響應的Server端。Server之間通過局域網或廣域網通信實現數據一致性。每個Server或Client都是一個consul agent。Consul集群間使用了GOSSIP協議通信和raft一致性算法。上面這張圖涉及到了很多術語:

  • Agent——agent是一直運行在Consul集群中每個成員上的守護進程。通過運行 consul agent來啟動。 agent可以運行在client或者server模式。指定節點作為client或者server是非常簡單的,除非有其他agent實例。所有的agent都能運行DNS或者HTTP接口,並負責運行時檢查和保持服務同步。

  • Client——一個Client是一個轉發所有RPC到server的代理。這個client是相對無狀態的。client唯一執行的后台活動是加入LAN

  • gossip池。這有一個最低的資源開銷並且僅消耗少量的網絡帶寬。

  • Server——一個server是一個有一組擴展功能的代理,這些功能包括參與Raft選舉,維護集群狀態,響應RPC查詢,與其他數據中心交互WANgossip和轉發查詢給leader或者遠程數據中心。

  • DataCenter——雖然數據中心的定義是顯而易見的,但是有一些細微的細節必須考慮。例如,在EC2中,多個可用區域被認為組成一個數據中心?我們定義數據中心為一個私有的,低延遲和高帶寬的一個網絡環境。這不包括訪問公共網絡,但是對於我們而言,同一個EC2中的多個可用區域可以被認為是一個數據中心的一部分。

  • Consensus——在我們的文檔中,我們使用Consensus來表明就leader選舉和事務的順序達成一致。由於這些事務都被應用到有限狀態機上,Consensus暗示復制狀態機的一致性。

  • Gossip——Consul建立在Serf的基礎之上,它提供了一個用於多播目的的完整的gossip協議。 Serf提供成員關系,故障檢測和事件廣播。更多的信息在gossip文檔中描述。這足以知道gossip使用基於UDP的隨機的點到點通信。

  • LAN Gossip——它包含所有位於同一個局域網或者數據中心的所有節點。 WAN

  • Gossip——它只包含Server。這些server主要分布在不同的數據中心並且通常通過因特網或者廣域網通信。

 

在每個數據中心,client和server是混合的。一般建議有3-5台server。這是基於有故障情況下的可用性和性能之間的權衡結果,因為越多的機器加入達成共識越慢。然而,並不限制client的數量,它們可以很容易的擴展到數千或者數萬台。

同一個數據中心的所有節點都必須加入gossip協議。這意味着gossip協議包含一個給定數據中心的所有節點。這服務於幾個目的:第一,不需要在client上配置server地址。發現都是自動完成的。第二,檢測節點故障的工作不是放在server上,而是分布式的。這是的故障檢測相比心跳機制有更高的可擴展性。第三:它用來作為一個消息層來通知事件,比如leader選舉發生時。

每個數據中心的server都是Raft節點集合的一部分。這意味着它們一起工作並選出一個leader,一個有額外工作的server。leader負責處理所有的查詢和事務。作為一致性協議的一部分,事務也必須被復制到所有其他的節點。因為這一要求,當一個非leader得server收到一個RPC請求時,它將請求轉發給集群leader(與zookeeper一樣)。

server節點也作為WAN gossip Pool的一部分。這個Pool不同於LAN Pool,因為它是為了優化互聯網更高的延遲,並且它只包含其他Consul server節點。這個Pool的目的是為了允許數據中心能夠以low-touch的方式發現彼此。這使得一個新的數據中心可以很容易的加入現存的WAN gossip。因為server都運行在這個pool中,它也支持跨數據中心請求。當一個server收到來自另一個數據中心的請求時,它隨即轉發給正確數據中想一個server。該server再轉發給本地leader。

這使得數據中心之間只有一個很低的耦合,但是由於故障檢測,連接緩存和復用,跨數據中心的請求都是相對快速和可靠的。

 

1、Consul的核心知識

Gossip協議

傳統的監控,如ceilometer,由於每個節點都會向server報告狀態,隨着節點數量的增加server的壓力隨之增大。在所有的Agent之間(包括服務器模式和普通模式)運行着Gossip協議。服務器節點和普通Agent都會加入這個Gossip集群,收發Gossip消息。每隔一段時間,每個節點都會隨機選擇幾個節點發送Gossip消息,其他節點會再次隨機選擇其他幾個節點接力發送消息。這樣一段時間過后,整個集群都能收到這條消息。示意圖如下

 

  

RAFT一致性算法

 

 

 

為了實現集群中多個ConsulServer中的數據保持一致性,consul使用了基於強一致性的RAFT算法。在Raft中,任何時候一個服務器可以扮演下面角色之一:

  1. Leader: 處理所有客戶端交互,日志復制等,一般一次只有一個Leader.

  2. Follower: 類似選民,完全被動

  3. Candidate(候選人): 可以被選為一個新的領導人。

 

Leader全權負責所有客戶端的請求,以及將數據同步到Follower中(同一時刻系統中只存在一個Leader)。Follower被動響應請求RPC,從不主動發起請求RPC。Candidate由Follower向Leader轉換的中間狀態。 關於RAFT一致性算法有一個經典的動畫http://thesecretlivesofdata.com/raft/,其中詳細介紹了選舉,數據同步的步驟。

 

 

 

2、Consul 集群搭建

 

 

首先需要有一個正常的Consul集群,有Server,有Leader。這里在服務器Server1、Server2、Server3上分別部署了Consul Server。(這些服務器上最好只部署Consul程序,以盡量維護Consul Server的穩定)

服務器Server4和Server5上通過Consul Client分別注冊Service A、B、C,這里每個微服務分別部署在了兩個服務器上,這樣可以避免Service的單點問題。(一般微服務和Client綁定)

在服務器Server6中Program D需要訪問Service B,這時候Program D首先訪問本機Consul Client提供的HTTP API,本機Client會將請求轉發到Consul Server,Consul Server查詢到Service B當前的信息返回

 

(1) 准備環境

服務器ip consul類型 Node(節點名稱) 序號
192.168.126.100 server server-1 s1
192.168.126.101 server server-2 s2
192.168.126.102 server server-3 s3
192.168.126.99 client client-1 s4

 

  • Agent 以 client 模式啟動的節點。在該模式下,該節點會采集相關信息,通過 RPC 的方式向server 發送。Client模式節點有無數個,官方建議搭配微服務配置

  • Agent 以 server 模式啟動的節點。一個數據中心中至少包含 1 個 server 節點。不過官方建議使用3 或 5 個 server 節點組建成集群,以保證高可用且不失效率。server 節點參與 Raft、維護會員信息、注冊服務、健康檢查等功能。

 

(2) 安裝consul並啟動

在每個consul節點上安裝consul服務,下載安裝過程和單節點一致。

##從官網下載最新版本的Consul服務
wget https://releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip
##使用unzip命令解壓到指定目錄下 /usr/local/myserver/consul
unzip consul_1.6.3_linux_amd64.zip -d /usr/local/myserver/consul
##測試一下
./consul

 

啟動每個consul server節點

##登錄s1虛擬機,以server形式運行
./consul agent -server -bootstrap-expect 3 -data-dir /etc/consul.d -node=server-1 -bind=192.168.126.100 -ui -client 0.0.0.0 &
##登錄s2 虛擬機,以server形式運行
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-2 -bind=192.168.126.101 -ui -client 0.0.0.0 &
##登錄s3 虛擬機,以server形式運行
./consul agent -server -bootstrap-expect 2 -data-dir /etc/consul.d -node=server-3 -bind=192.168.126.102 -ui -client 0.0.0.0 &

 

-server: 表示該 agent是一個 serverAgent,不添加這個選項則表示是一個 clientAgent

-bootstrap-expect:該命令通知 consul 准備加入集群的節點個數,集群要求的最少server數量,當低於這個數量,集群即失效。

-data-dir:表示相關數據存儲的目錄位置,在 serverAgent上該命令所指示的目錄下會存儲一些集群的狀態信息

-node:節點id,在同一集群不能重復。 -bind:指定 agent 的 Ip。

-client:客戶端的ip地址(0.0.0.0表示不限制),如不添加該指令,則 UI 只能在當前機器上訪問

-join: 將該節點加入集群中

& :在后台運行,此為linux腳本語法

至此三個Consul Server模式服務全部啟動成功。

啟動s4,使用client形式啟動consul

##登錄s2 虛擬機中使用client形式啟動consul
./consul agent -client=0.0.0.0 -data-dir /etc/consul.d -node=client-1 -bind=192.168.126.99 -ui &

 

(3) 每個節點加入集群

防火牆打開每個consul服務的相關端口

firewall-cmd --zone=public --add-port=8300/tcp --permanent
firewall-cmd --zone=public --add-port=8301/tcp --permanent
firewall-cmd --zone=public --add-port=8500/tcp --permanent
firewall-cmd --reload   #重啟防火牆

 

以s1為leader,在s2,s3,s4 服務其上通過consul join 命令加入 s1中的consul集群中

##加入consul集群
./consul join 192.168.126.100

 

(4) 測試

在任意一台服務器中輸入 consul members查看集群中的所有節點信息

##查看consul集群節點信息
./consul members

 

 

 

 

訪問 http://192.168.126.99:8500/ui/dc1/services

 

 

 

 

 

3、Consul 常見問題

(1)節點和服務注銷

當服務或者節點失效,Consul不會對注冊的信息進行剔除處理,僅僅標記已狀態進行標記(並且不可使用)。如果擔心失效節點和失效服務過多影響監控。可以通過調用HTTP API的形式進行處理

節點和服務的注銷可以使用HTTP API:

  • 注銷任意節點和服務:/catalog/deregister

  • 注銷當前節點的服務:/agent/service/deregister/:service_id

     

如果某個節點不繼續使用了,也可以在本機使用consul leave命令,或者在其它節點使用consul force-leave 節點Id。

(2)健康檢查與故障轉移

在集群環境下,健康檢查是由服務注冊到的Agent來處理的,那么如果這個Agent掛掉了,那么此節點的健康檢查就處於無人管理的狀態。

從實際應用看,節點上的服務可能既要被發現,又要發現別的服務,如果節點掛掉了,僅提供被發現的功能實際上服務還是不可用的。當然發現別的服務也可以不使用本機節點,可以通過訪問一個Nginx實現的若干Consul節點的負載均衡來實現。

 

 

 

 


感謝itheima提供的材料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM