用例spring_cloud_consul
項目地址:傳送門
Eureka替換方案Consul
在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 是 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 |
-
-
value的值經過了base64_encode,獲取到數據后base64_decode才能獲取到原始值。數據不能大於512Kb
-
四、項目引入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中,任何時候一個服務器可以扮演下面角色之一:
-
Leader: 處理所有客戶端交互,日志復制等,一般一次只有一個Leader.
-
Follower: 類似選民,完全被動
-
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掛掉了,那么此節點的健康檢查就處於無人管理的狀態。