consul概念解析,集群搭建及作為配置中心與spring cloud集成
Consul是什么?
Consul 官方站點:https://www.consul.io/
官方介紹是:Consul 是一種服務(wù)網(wǎng)格的解決方案,在 Consul 中,提供了服務(wù)發(fā)現(xiàn)、配置、分段等控制管理平臺,Consul 中的每項功能都可以單獨使用,也可以一起使用來構(gòu)建完整的服務(wù)網(wǎng)格;在 Consul 內(nèi)部,有一個簡單的代理服務(wù),所以在安裝 Consul 后,馬上就可以開始使用 Consul ;當(dāng)然,Consul 也支持集成第三方代理,比如 Envoy。
Consul 是一個服務(wù)組件,在用戶下載 Consul 的安裝包后,可以立即運行它,或者通過其它托管程序運行它,Consul 只有一個程序包,無需另行安裝;當(dāng)運行 Consul 的時候,需要為其指定一些必須的參數(shù),以供 Consul 在運行時使用;(比如參數(shù) -data-dir 表示指定 Consul 存放數(shù)據(jù)的目錄)。
我們不整那些服務(wù)網(wǎng)格之類的概念,簡單說,Consul在整個微服務(wù)架構(gòu)體系里面就是起了注冊中心和配置中心的作用。
Consul功能概述
服務(wù)注冊
Consul 內(nèi)部偵聽 8500 端口,提供給 Consul 的客戶端注冊服務(wù),比如張三開發(fā)了一個購物車程序,該購物車程序包含了“加入購物車”、“清空購物車” 兩個接口,張三在開發(fā)購物車程序的時候,使用了 Consul 的客戶端包組件,在程序運行起來以后,購物車程序就自動的連接到 Consul 的 8500 端口,注冊了一個服務(wù),該服務(wù)被命名為“購物車程序”,此時,Consul 并不知道 “購物車程序”有多少個接口,Consul 只知道 “購物車程序”的服務(wù)地址、端口。
服務(wù)發(fā)現(xiàn)
在“購物車程序”注冊到 Consul 后,Consul 也僅僅知道有這么一個服務(wù)注冊進來了,并且還配置了健康檢查, Consul 會定時的去連接 “購物車程序”,確保其還處于可提供服務(wù)的狀態(tài),任何人(程序)都可以通過 Consul 的外部地址訪問 Consul 內(nèi)部的已注冊的服務(wù)列表,從而獲得真實的服務(wù)地址,然后調(diào)用該真實地址,獲得結(jié)果。
鍵值存儲
在 Consul 內(nèi)部,提供了簡單的數(shù)據(jù)存儲,也就是 key/value 系統(tǒng),kv 系統(tǒng)非常強大,它的作用包括允許節(jié)點動態(tài)修改配置、執(zhí)行 leader 選舉、服務(wù)發(fā)現(xiàn)、集成健康檢查、或者其它你想要存儲到 Consul 中的內(nèi)容
Consul部署架構(gòu)
集群
Consul 是一個分布式的解決方案,可以部署多個 Consul 實例,確保數(shù)據(jù)中心的持續(xù)穩(wěn)定,在 Consul 集群中,內(nèi)部采用投票的方式選舉出 leader,然后才開始運行整個集群,只有正確選舉出 leader 后,集群才開始工作,當(dāng)一個服務(wù)注冊到 Consul 后,集群將該服務(wù)進行同步,確保 Consul 集群內(nèi)的每個節(jié)點都存儲了該服務(wù)的信息;然后,Consul 集群將對該服務(wù)進行健康檢查和投票,超過半數(shù)通過,即認為該服務(wù)為正常(或者異常);一旦被投票認定為異常的服務(wù),該服務(wù)將不會被外部發(fā)現(xiàn)(不可訪問),在此過程中,Consul 將持續(xù)的對該異常的服務(wù)進行檢查,一旦服務(wù)恢復(fù),Consul 即刻將其加入正常服務(wù)。
服務(wù)器和客戶端
Consul 支持兩種運行的方式,即 server 和 client 模式,當(dāng)一個 Consul 節(jié)點以 server 模式運行的時候,就表示該 Consul 節(jié)點會存儲服務(wù)和配置等相關(guān)信息,并且參與到健康檢查、leader 選舉等服務(wù)器事務(wù)中,與之相反的是,client 模式不會存儲服務(wù)信息。
數(shù)據(jù)中心
每個 Consul 節(jié)點都需要加入一個命名的數(shù)據(jù)中心(DataCenter),一個節(jié)點上,可以運行多個數(shù)據(jù)中心,數(shù)據(jù)中心的作用在于應(yīng)用隔離,相當(dāng)于服務(wù)分組。可以簡單理解為,一個數(shù)據(jù)中心域為一個二層聯(lián)通的子網(wǎng)。
下圖為consul的官方架構(gòu)圖:

Consul能做什么?
簡單來說,consul是一個分布式的服務(wù)管理平臺,應(yīng)用可以利用consul來進行分布式服務(wù)的服務(wù)注冊、服務(wù)發(fā)現(xiàn)、配置管理、分布式事務(wù)協(xié)調(diào)等功能。借助于raft共識算法,可以輕松搭建出一個高可用的分布式集群,各節(jié)點所存儲的數(shù)據(jù)通過raft算法可以保證最終一致性,而不需要依賴于任何的外部數(shù)據(jù)庫。(這點非常重要,要知道搭建一個高可用的mysql數(shù)據(jù)庫本身成本就非常高,nacos的數(shù)據(jù)存儲目前只支持mysql,現(xiàn)在貌似也有規(guī)劃轉(zhuǎn)分布式算法)。通過上面的介紹,相信你也看出來了,consul做的事情本質(zhì)上和zookeeper、etcd這些分布式服務(wù)組件都差不多,只是zookeeper用的一致性算法是zab(基于paxos),向來以難以理解著稱,而etcd也是raft算法,相對容易理解很多,但是不帶ui管理界面,易用性方面consul會好一點
集群搭建
下載安裝
consul安裝非常簡單,直接在官網(wǎng)下載對應(yīng)操作系統(tǒng)編譯好的二進制文件就行,網(wǎng)址為https://www.consul.io/downloads.html。整個壓縮包就一個二進制文件consul,拷貝至系統(tǒng)的/usr/bin就ok了。執(zhí)行consul,看到如下輸出,說明安裝成功:
[consul@localhost ~]$ consul
Usage: consul [--version] [--help] <command> [<args>]
Available commands are:
acl Interact with Consul's ACLs
agent Runs a Consul agent
catalog Interact with the catalog
config Interact with Consul's Centralized Configurations
connect Interact with Consul Connect
debug Records a debugging archive for operators
event Fire a new event
exec Executes a command on Consul nodes
force-leave Forces a member of the cluster to enter the "left" state
info Provides debugging information for operators.
intention Interact with Connect service intentions
join Tell Consul agent to join cluster
keygen Generates a new encryption key
keyring Manages gossip layer encryption keys
kv Interact with the key-value store
leave Gracefully leaves the Consul cluster and shuts down
lock Execute a command holding a lock
login Login to Consul using an auth method
logout Destroy a Consul token created with login
maint Controls node or service maintenance mode
members Lists the members of a Consul cluster
monitor Stream logs from a Consul agent
operator Provides cluster-level tools for Consul operators
reload Triggers the agent to reload configuration files
rtt Estimates network round trip time between nodes
services Interact with services
snapshot Saves, restores and inspects snapshots of Consul server state
tls Builtin helpers for creating CAs and certificates
validate Validate config files/directories
version Prints the Consul version
watch Watch for changes in Consul
consul參數(shù)說明
- agent:是consul的核心指令,它運行agent來維護成員的重要信息、運行檢查、服務(wù)宣布、查詢處理等等。
- event:提供了一種機制,用來fire自定義的用戶事件,這些事件對consul來說是不透明的,但它們可以用來構(gòu)建自動部署、重啟服務(wù)或者其他行動的腳本。
- exec:提供了一種遠程執(zhí)行機制,比如你要在所有的機器上執(zhí)行uptime命令,遠程執(zhí)行的工作通過job來指定,存儲在KV中。agent使用event系統(tǒng)可以快速的知道有新的job產(chǎn)生,消息是通過gossip協(xié)議來傳遞的,因此消息傳遞是最佳的,但是并不保證命令的執(zhí)行。事件通過gossip來驅(qū)動,遠程執(zhí)行依賴KV存儲系統(tǒng)(就像消息代理一樣)。
- force-leave:可以強制consul集群中的成員進入left狀態(tài)(空閑狀態(tài)),記住,即使一個成員處于活躍狀態(tài),它仍舊可以再次加入集群中,這個方法的真實目的是強制移除failed的節(jié)點。如果failed的節(jié)點還是網(wǎng)絡(luò)的一部分,則consul會周期性的重新鏈接failed的節(jié)點,如果經(jīng)過一段時間后(默認是72小時),consul則會宣布停止嘗試鏈接failed的節(jié)點。force-leave指令可以快速的把failed節(jié)點轉(zhuǎn)換到left狀態(tài)。
- info:提供了各種操作時可以用到的debug信息,對于client和server,info有返回不同的子系統(tǒng)信息,目前有以下幾個KV信息:agent(提供agent信息),consul(提供consul庫的信息),raft(提供raft庫的信息),serf_lan(提供LAN gossip pool),serf_wan(提供WAN gossip pool)。
- join:告訴consul agent加入一個已經(jīng)存在的集群中,一個新的consul agent必須加入一個已經(jīng)有至少一個成員的集群中,這樣它才能加入已經(jīng)存在的集群中,如果你不加入一個已經(jīng)存在的集群,則agent是它自身集群的一部分,其他agent則可以加入進來。agent可以加入其他agent多次。如果你想加入多個集群,則可以寫多個地址,consul會加入所有的地址。
- keygen:生成加密的密鑰,可以用在consul agent通訊加密。
leave指令觸發(fā)一個優(yōu)雅的離開動作并關(guān)閉agent,節(jié)點離開后不會嘗試重新加入集群中。運行在server狀態(tài)的節(jié)點,節(jié)點會被優(yōu)雅的刪除,這是很嚴(yán)重的,在某些情況下一個不優(yōu)雅的離開會影響到集群的可用性。 - members:輸出consul agent目前所知道的所有的成員以及它們的狀態(tài),節(jié)點的狀態(tài)只有alive、left、failed三種狀態(tài)。
- monitor:用來鏈接運行的agent,并顯示日志。monitor會顯示最近的日志,并持續(xù)的顯示日志流,不會自動退出,除非你手動或者遠程agent自己退出。
- reload:可以重新加載agent的配置文件。SIGHUP指令在重新加載配置文件時使用,任何重新加載的錯誤都會寫在agent的log文件中,并不會打印到屏幕。
- version:打印consul的版本
- watch:提供了一個機制,用來監(jiān)視實際數(shù)據(jù)視圖的改變(節(jié)點列表、成員服務(wù)、KV),如果沒有指定進程,當(dāng)前值會被dump出來。
agent參數(shù)說明
核心對象的agent,我們來看一下它的啟動參數(shù)
[consul@localhost ~]$ consul agent --help
Usage: consul agent [options]
Starts the Consul agent and runs until an interrupt is received. The
agent represents a single node in a cluster.
HTTP API Options
-datacenter=<value>
Datacenter of the agent.
Command Options
-advertise=<value>
Sets the advertise address to use.
-advertise-wan=<value>
Sets address to advertise on WAN instead of -advertise address.
-allow-write-http-from=<value>
Only allow write endpoint calls from given network. CIDR format,
can be specified multiple times.
-alt-domain=<value>
Alternate domain to use for DNS interface.
-bind=<value>
Sets the bind address for cluster communication.
-bootstrap
Sets server to bootstrap mode.
-bootstrap-expect=<value>
Sets server to expect bootstrap mode.
-check_output_max_size=<value>
Sets the maximum output size for checks on this agent
-client=<value>
Sets the address to bind for client access. This includes RPC, DNS,
HTTP, HTTPS and gRPC (if configured).
-config-dir=<value>
Path to a directory to read configuration files from. This
will read every file ending in '.json' as configuration in this
directory in alphabetical order. Can be specified multiple times.
-config-file=<value>
Path to a file in JSON or HCL format with a matching file
extension. Can be specified multiple times.
-config-format=<value>
Config files are in this format irrespective of their extension.
Must be 'hcl' or 'json'
-data-dir=<value>
Path to a data directory to store agent state.
-dev
Starts the agent in development mode.
-disable-host-node-id
Setting this to true will prevent Consul from using information
from the host to generate a node ID, and will cause Consul to
generate a random node ID instead.
-disable-keyring-file
Disables the backing up of the keyring to a file.
-dns-port=<value>
DNS port to use.
-domain=<value>
Domain to use for DNS interface.
-enable-local-script-checks
Enables health check scripts from configuration file.
-enable-script-checks
Enables health check scripts.
-encrypt=<value>
Provides the gossip encryption key.
-grpc-port=<value>
Sets the gRPC API port to listen on (currently needed for Envoy xDS
only).
-hcl=<value>
hcl config fragment. Can be specified multiple times.
-http-port=<value>
Sets the HTTP API port to listen on.
-join=<value>
Address of an agent to join at start time. Can be specified
multiple times.
-join-wan=<value>
Address of an agent to join -wan at start time. Can be specified
multiple times.
-log-file=<value>
Path to the file the logs get written to
-log-level=<value>
Log level of the agent.
-log-rotate-bytes=<value>
Maximum number of bytes that should be written to a log file
-log-rotate-duration=<value>
Time after which log rotation needs to be performed
-log-rotate-max-files=<value>
Maximum number of log file archives to keep
-node=<value>
Name of this node. Must be unique in the cluster.
-node-id=<value>
A unique ID for this node across space and time. Defaults to a
randomly-generated ID that persists in the data-dir.
-node-meta=<key:value>
An arbitrary metadata key/value pair for this node, of the format
`key:value`. Can be specified multiple times.
-non-voting-server
(Enterprise-only) This flag is used to make the server not
participate in the Raft quorum, and have it only receive the data
replication stream. This can be used to add read scalability to
a cluster in cases where a high volume of reads to servers are
needed.
-pid-file=<value>
Path to file to store agent PID.
-protocol=<value>
Sets the protocol version. Defaults to latest.
-raft-protocol=<value>
Sets the Raft protocol version. Defaults to latest.
-recursor=<value>
Address of an upstream DNS server. Can be specified multiple times.
-rejoin
Ignores a previous leave and attempts to rejoin the cluster.
-retry-interval=<value>
Time to wait between join attempts.
-retry-interval-wan=<value>
Time to wait between join -wan attempts.
-retry-join=<value>
Address of an agent to join at start time with retries enabled. Can
be specified multiple times.
-retry-join-wan=<value>
Address of an agent to join -wan at start time with retries
enabled. Can be specified multiple times.
-retry-max=<value>
Maximum number of join attempts. Defaults to 0, which will retry
indefinitely.
-retry-max-wan=<value>
Maximum number of join -wan attempts. Defaults to 0, which will
retry indefinitely.
-segment=<value>
(Enterprise-only) Sets the network segment to join.
-serf-lan-bind=<value>
Address to bind Serf LAN listeners to.
-serf-lan-port=<value>
Sets the Serf LAN port to listen on.
-serf-wan-bind=<value>
Address to bind Serf WAN listeners to.
-serf-wan-port=<value>
Sets the Serf WAN port to listen on.
-server
Switches agent to server mode.
-server-port=<value>
Sets the server port to listen on.
-syslog
Enables logging to syslog.
-ui
Enables the built-in static web UI server.
-ui-content-path=<value>
Sets the external UI path to a string. Defaults to: /ui/
-ui-dir=<value>
Path to directory containing the web UI resources.
- -advertise:通知展現(xiàn)地址用來改變我們給集群中的其他節(jié)點展現(xiàn)的地址,一般情況下-bind地址就是展現(xiàn)地址
- -bootstrap:用來控制一個server是否在bootstrap模式,在一個datacenter中只能有一個server處于bootstrap模式,當(dāng)一個server處于bootstrap模式時,可以自己選舉為raft leader。
- -bootstrap-expect:在一個datacenter中期望提供的server節(jié)點數(shù)目,當(dāng)該值提供的時候,consul一直等到達到指定sever數(shù)目的時候才會引導(dǎo)整個集群,該標(biāo)記不能和bootstrap公用。
- -bind:該地址用來在集群內(nèi)部的通訊,集群內(nèi)的所有節(jié)點到地址都必須是可達的,默認是0.0.0.0。
- -client:consul綁定在哪個client地址上,這個地址提供HTTP、DNS、RPC等服務(wù),默認是127.0.0.1。
- -config-file:明確的指定要加載哪個配置文件
- -config-dir:配置文件目錄,里面所有以.json結(jié)尾的文件都會被加載
- -data-dir:提供一個目錄用來存放agent的狀態(tài),所有的agent都需要該目錄,該目錄必須是穩(wěn)定的,系統(tǒng)重啟后都繼續(xù)存在。
- -dc:該標(biāo)記控制agent的datacenter的名稱,默認是dc1。
- -encrypt:指定secret key,使consul在通訊時進行加密,key可以通過consul keygen生成,同一個集群中的節(jié)點必須使用相同的key。
- -join:加入一個已經(jīng)啟動的agent的ip地址,可以多次指定多個agent的地址。如果consul不能加入任何指定的地址中,則agent會啟動失敗。默認agent啟動時不會加入任何節(jié)點。
- -retry-join:和join類似,但是允許你在第一次失敗后進行嘗試。
- -retry-interval:兩次join之間的時間間隔,默認是30s。
- -retry-max:嘗試重復(fù)join的次數(shù),默認是0,也就是無限次嘗試。
- -log-level:consul agent啟動后顯示的日志信息級別。默認是info,可選:trace、debug、info、warn、err。
- -node:節(jié)點在集群中的名稱,在一個集群中必須是唯一的,默認是該節(jié)點的主機名。
- -protocol:consul使用的協(xié)議版本。
- -rejoin:使consul忽略先前的離開,在再次啟動后仍舊嘗試加入集群中。
- -server:定義agent運行在server模式,每個集群至少有一個server,建議每個集群的server不要超過5個。
- -syslog:開啟系統(tǒng)日志功能,只在linux/osx上生效。
- -ui-dir:提供存放web ui資源的路徑,該目錄必須是可讀的。
- -pid-file:提供一個路徑來存放pid文件,可以使用該文件進行SIGINT/SIGHUP(關(guān)閉/更新)agent。
啟動節(jié)點
了解了參數(shù)之后,我們就可以來啟動集群了。這次我們規(guī)劃了三個節(jié)點(一般建議為奇數(shù)節(jié)點),啟動命令如下:
// 22.196.248.71
consul agent -server -ui -bootstrap -data-dir=/data/consul -node=agent-1 -client=0.0.0.0 -bind=22.196.248.71 -datacenter=dc1
// 22.196.248.73
consul agent -server -ui -data-dir=/data/consul -node=agent-2 -client=0.0.0.0 -bind=22.196.248.73 -datacenter=dc1 -join 22.196.248.71
// 22.196.248.74
consul agent -server -ui -data-dir=/data/consul -node=agent-3 -client=0.0.0.0 -bind=22.196.248.74 -datacenter=dc1 -join 22.196.248.71
解釋一下上面的指令,簡單來說,就是指定當(dāng)前主機客戶端偵聽地址為-client=0.0.0.0(這個參數(shù)指定了客戶端允許接入的地址,0.0.0.0為任意地址可以接入,默認為127.0.0.1,即只有本機能接入),綁定了當(dāng)前主機的IP地址(-bind,多網(wǎng)卡的話必須要設(shè)置,讓consul知道使用哪個ip作為節(jié)點的ip),指定了一個數(shù)據(jù)中心的名稱(-datacenter=dc1),后兩臺服務(wù)器在啟動的時候加入第一臺代理服務(wù)器(-join 22.196.248.71),同時指定了啟用每臺服務(wù)器的內(nèi)置 WebUI 服務(wù)器組件(-ui),當(dāng)三臺服務(wù)器都正確運行起來以后,Consul 集群將自動選舉 leader,自動進行集群事務(wù),無需干預(yù)。
這里需要注意一點,理論上consul節(jié)點起來之后可以通過raft算法自動選舉leader出來,但是我這邊沒有成功,日志提示選舉失敗,需要通過設(shè)置-bootstrap參數(shù)先啟動某個節(jié)點,這個節(jié)點會自動把自己設(shè)置為leader,后面啟動的節(jié)點就可以正常加入了。具體原因未知,有高手知道的請指點一下
此時訪問任意一臺服務(wù)器的http://ip:8500,都可以看到ui界面

看到這個界面說明三個節(jié)點都正常啟動了,我們在key/value插入一些數(shù)據(jù),可以看到在三個節(jié)點都能正確查詢到,集群bootstrap成功。
Spring Cloud 集成
配置中心
這邊我們看看如何與spring cloud集成,使用consul作為應(yīng)用的配置中心。為簡單起見我們使用zuul網(wǎng)關(guān)作為示例,只使用了配置中心功能,沒用注冊中心功能
在zuul的pom文件中添加如下依賴:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>
</dependencies>
修改配置文件(注意要使用bootstrap.yml進行配置,不要用application.yml,否則配置不會起作用)
spring:
application:
name: bocsh-gateway
cloud:
consul:
host: 22.196.248.71
port: 8500
config:
enabled: true
format: yaml
#data-key表示consul上面的KEY值(或者說文件的名字) ,默認是data
#prefix設(shè)置配置值的基本文件夾,默認為config
#defaultContext設(shè)置所有應(yīng)用程序使用的文件夾名稱,默認為spring的應(yīng)用名稱
#profileSeparator設(shè)置用于使用配置文件在屬性源中分隔配置文件名稱的分隔符的值,默認為逗號
server:
port: 30080
注意data-key,prefix,defaultContext,profileSeparator這幾個配置都是可選項,定義了我們的配置文件在consul中存儲的目錄結(jié)構(gòu),spring boot 在啟動時會在這個路徑下獲取配置文件信息,如果都是使用默認值得話,在consul中存儲的數(shù)據(jù)結(jié)構(gòu)如下(默認讀取的是default配置):

key為
config/bocsh-gateway/data
動態(tài)配置更新
首先,spring cloud consul組件是有動態(tài)更新配置能力的,官方稱之為Config Watch。原理是consul客戶端定時向consul服務(wù)端發(fā)起一個http請求,以檢測服務(wù)端的配置是否有更新(類似于在actuator端點執(zhí)行/refresh操作,但consul是自動的,不需要專門觸發(fā)),相關(guān)配置如下:
spring:
cloud:
consul:
config:
watch:
enable: #default true
wait-time: #default 55
delay: #default 1000
可以看到配置更新能力默認是開啟的,不想動態(tài)更新的話可以通過設(shè)置spring.cloud.consul.config.watch.enabled=false關(guān)閉Config Watch功能。
有了上面的知識,我們就可以來配置動態(tài)路由了,首先在啟動主類下加入如下配置:
@EnableZuulProxy
@SpringBootApplication
public class BaseApplication {
public static void main(String[] args) {
SpringApplication.run(BaseApplication.class, args);
}
@RefreshScope
@ConfigurationProperties("zuul")
public ZuulProperties zuulProperties(){
return new ZuulProperties();
}
}
在配置文件中打開actuator的routes端點,使我們可以觀察routes變化的情況
management:
endpoints:
web:
exposure:
include: routes
修改consul中的key/value值,通過訪問http://ip:port/actuator/routes可以看到zuul目前的最新路由表,配置實時更新,實現(xiàn)了動態(tài)配置功能。
這里需要注意一點,如果你改的是zuul路由表中的
path部分,則原有的路由信息不會消息,會新增一條你修改后的路由信息,修改url部分則可以實時生效。
參考資料
1.https://www.cnblogs.com/linjiqin/p/9718223.html
2.https://blog.csdn.net/it_lihongmin/article/details/91357445
3.https://consul.io
4.https://cloud.spring.io/spring-cloud-static/spring-cloud-consul/2.1.3.RELEASE/single/spring-cloud-consul.html