相關(guān)源碼: spring cloud demo
什么是服務(wù)發(fā)現(xiàn)
微服務(wù)的框架體系中昂拂,服務(wù)發(fā)現(xiàn)是不能不提的一個模塊。我相信了解或者熟悉微服務(wù)的童鞋應(yīng)該都知道它的重要性剖膳。這里我只是簡單的提一下魏颓,畢竟這不是我們的重點(diǎn)。我們看下面的一幅圖片:
圖中吱晒,客戶端的一個接口甸饱,需要調(diào)用服務(wù)A-N÷乇簦客戶端必須要知道所有服務(wù)的網(wǎng)絡(luò)位置的叹话,以往的做法是配置是配置文件中,或者有些配置在數(shù)據(jù)庫中躏精。這里就帶出幾個問題:
- 需要配置N個服務(wù)的網(wǎng)絡(luò)位置渣刷,加大配置的復(fù)雜性
- 服務(wù)的網(wǎng)絡(luò)位置變化,都需要改變每個調(diào)用者的配置
- 集群的情況下矗烛,難以做負(fù)載(反向代理的方式除外)
總結(jié)起來一句話:服務(wù)多了辅柴,配置很麻煩,問題多多
既然有這些問題瞭吃,那么服務(wù)發(fā)現(xiàn)就是解決這些問題的碌嘀。話說,怎么解決呢歪架?我們再看一張圖
與之前一張不同的是股冗,加了個服務(wù)發(fā)現(xiàn)模塊。圖比較簡單和蚪,這邊文字描述下止状。服務(wù)A-N把當(dāng)前自己的網(wǎng)絡(luò)位置注冊到服務(wù)發(fā)現(xiàn)模塊(這里注冊的意思就是告訴)烹棉,服務(wù)發(fā)現(xiàn)就以K-V的方式記錄下,K一般是服務(wù)名怯疤,V就是IP:PORT浆洗。服務(wù)發(fā)現(xiàn)模塊定時的輪詢查看這些服務(wù)能不能訪問的了(這就是健康檢查)〖停客戶端在調(diào)用服務(wù)A-N的時候伏社,就跑去服務(wù)發(fā)現(xiàn)模塊問下它們的網(wǎng)絡(luò)位置,然后再調(diào)用它們的服務(wù)塔淤。這樣的方式是不是就可以解決上面的問題了呢摘昌?客戶端完全不需要記錄這些服務(wù)網(wǎng)絡(luò)位置,客戶端和服務(wù)端完全解耦高蜂!
這個過程大體是這樣聪黎,當(dāng)然服務(wù)發(fā)現(xiàn)模塊沒這么簡單。里面包含的東西還很多妨马。這樣表述只是方便理解挺举。
圖中的服務(wù)發(fā)現(xiàn)模塊基本上就是微服務(wù)架構(gòu)中服務(wù)發(fā)現(xiàn)的作用了。
consul 簡介
做服務(wù)發(fā)現(xiàn)的框架常用的有
- zookeeper
- eureka
- etcd
- consul
這里就不比較哪個好哪個差了烘跺,需要的童鞋自己谷歌百度湘纵。
那么consul是啥?consul就是提供服務(wù)發(fā)現(xiàn)的工具滤淳。然后下面是簡單的介紹:
consul是分布式的梧喷、高可用、橫向擴(kuò)展的脖咐。consul提供的一些關(guān)鍵特性:
- service discovery:consul通過DNS或者HTTP接口使服務(wù)注冊和服務(wù)發(fā)現(xiàn)變的很容易铺敌,一些外部服務(wù),例如saas提供的也可以一樣注冊屁擅。
- health checking:健康檢測使consul可以快速的告警在集群中的操作偿凭。和服務(wù)發(fā)現(xiàn)的集成,可以防止服務(wù)轉(zhuǎn)發(fā)到故障的服務(wù)上面派歌。
- key/value storage:一個用來存儲動態(tài)配置的系統(tǒng)弯囊。提供簡單的HTTP接口,可以在任何地方操作胶果。
- multi-datacenter:無需復(fù)雜的配置匾嘱,即可支持任意數(shù)量的區(qū)域。
我們這里會介紹服務(wù)發(fā)現(xiàn)早抠,健康檢查霎烙,還有一些基本KV存儲。多數(shù)據(jù)中心有機(jī)會另一篇文章再說。
總結(jié):只要知道它是解決我上一部分提出的問題就行悬垃,其它的東西慢慢理解
consul的幾個概念
上圖是我從consul官方文檔摳出來的游昼。
我們只看數(shù)據(jù)中心1,可以看出consul的集群是由N個SERVER盗忱,加上M個CLIENT組成的酱床。而不管是SERVER還是CLIENT,都是consul的一個節(jié)點(diǎn)趟佃,所有的服務(wù)都可以注冊到這些節(jié)點(diǎn)上,正是通過這些節(jié)點(diǎn)實(shí)現(xiàn)服務(wù)注冊信息的共享昧捷。除了這兩個闲昭,還有一些小細(xì)節(jié),一一簡單介紹靡挥。
-
CLIENT
CLIENT表示consul的client模式序矩,就是客戶端模式。是consul節(jié)點(diǎn)的一種模式跋破,這種模式下簸淀,所有注冊到當(dāng)前節(jié)點(diǎn)的服務(wù)會被轉(zhuǎn)發(fā)到SERVER,本身是不持久化這些信息毒返。
-
SERVER
SERVER表示consul的server模式租幕,表明這個consul是個server,這種模式下拧簸,功能和CLIENT都一樣劲绪,唯一不同的是,它會把所有的信息持久化的本地盆赤,這樣遇到故障贾富,信息是可以被保留的。
-
SERVER-LEADER
中間那個SERVER下面有LEADER的字眼牺六,表明這個SERVER是它們的老大颤枪,它和其它SERVER不一樣的一點(diǎn)是,它需要負(fù)責(zé)同步注冊的信息給其它的SERVER淑际,同時也要負(fù)責(zé)各個節(jié)點(diǎn)的健康監(jiān)測畏纲。
-
其它信息
其它信息包括它們之間的通信方式,還有一些協(xié)議信息庸追,算法霍骄。它們是用于保證節(jié)點(diǎn)之間的數(shù)據(jù)同步,實(shí)時性要求等等一系列集群問題的解決淡溯。這些有興趣的自己看看官方文檔读整。
consul 基本使用
自己就一臺機(jī)子,所以這里就演示下docker下部署使用consul咱娶。容器與宿主機(jī)的端口映射忽略米间,正常生產(chǎn)環(huán)境每個宿主機(jī)一個consul强品,端口需要映射到宿主機(jī)
部署
拉取鏡像
docker search consul
咱們用官方的鏡像玩玩
docker pull consul
不指定tag就拉取last,當(dāng)前版本是0.8.0
啟動consul
-
啟動節(jié)點(diǎn)1(server模式)
docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' --name=node1 consul agent -server -bind=172.17.0.2 -bootstrap-expect=3 -node=node1
-node:節(jié)點(diǎn)的名稱
-bind:綁定的一個地址屈糊,用于節(jié)點(diǎn)之間通信的地址的榛,可以是內(nèi)外網(wǎng),必須是可以訪問到的地址
-server:這個就是表示這個節(jié)點(diǎn)是個SERVER
-bootstrap-expect:這個就是表示期望提供的SERVER節(jié)點(diǎn)數(shù)目逻锐,數(shù)目一達(dá)到夫晌,它就會被激活,然后就是LEADER了
-
啟動節(jié)點(diǎn)2-3(server模式)
docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' --name=node2 consul agent -server -bind=172.17.0.3 -join=172.17.0.2 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node2 docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' --name=node3 consul agent -server -bind=172.17.0.4 -join=172.17.0.2 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node3 -client=172.17.0.4
-join:這個表示啟動的時候昧诱,要加入到哪個集群內(nèi)晓淀,這里就是說要加入到節(jié)點(diǎn)1的集群
-node-id:這個貌似版本8才加入的,這里用這個來指定唯一的節(jié)點(diǎn)ID盏档,可以查看這個issue
-client:這個表示注冊或者查詢等一系列客戶端對它操作的IP凶掰,如果不指定這個IP,默認(rèn)是127.0.0.1蜈亩。
-
啟動節(jié)點(diǎn)4(client模式)
docker run -d -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate": true}' --name=node4 consul agent -bind=172.17.0.5 -retry-join=172.17.0.2 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node4
除了沒有-server懦窘,其它都是一樣的,沒有這個就說明這個節(jié)點(diǎn)是CLIENT
-
查看下集群的狀態(tài)
docker exec -t node1 consul members
4個節(jié)點(diǎn)都列出來了稚配。Status表示它們的狀態(tài)畅涂,都是alive。Type表示它們的類型药有,三個SERVER一個CLIENT毅戈,和我們之前啟動的一樣。DC表示數(shù)據(jù)中心愤惰,都是dc1苇经。
-
節(jié)點(diǎn)異常consul的處理
-
LEADER 掛了
leader掛了,consul會重新選取出新的leader宦言,只要超過一半的SERVER還活著扇单,集群是可以正常工作的。node1是leader奠旺,所以把這個容器停了蜘澜。docker stop node1
看看其他節(jié)點(diǎn)的日志(node2):
日志打印,心跳檢查node1的ip超時响疚,接著開始選舉鄙信。node2被選舉為新的leader。我們查看下現(xiàn)在的leader:
curl http://172.17.0.4:8500/v1/status/leader
返回的內(nèi)容:
"172.17.0.3:8300"
172.17.0.3 就是 node2節(jié)點(diǎn)的IP
(補(bǔ)充內(nèi)容)節(jié)點(diǎn)與宿主機(jī)的端口映射
指定node1與宿主機(jī)(192.168.99.100)的端口映射
docker run -d --net=host -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' --name=node1 -p 8300:8300 -p 8301:8301 -p 8301:8301/udp -p 8302:8302/udp -p 8302:8302 -p 8400:8400 -p 8500:8500 -p 53:53/udp -h consul consul agent -server -bind=172.17.0.2 -bootstrap -node=node1
node2進(jìn)入的IP指定為宿主機(jī)的IP
docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' --name=node2 consul agent -server -bind=172.17.0.3 -join=192.168.99.100 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=node2
正常加入忿晕,node1的日志:
2017/04/09 05:53:08 [INFO] serf: EventMemberJoin: node2 172.17.0.3
2017/04/09 05:53:08 [INFO] consul: Adding LAN server node2 (Addr: tcp/172.17.0.3:8300) (DC: dc1)
2017/04/09 05:53:08 [INFO] raft: Updating configuration with AddStaging (172.17.0.3:8300, 172.17.0.3:8300) to [{Suffrage:Voter ID:172.17.0.2:8300 Address:172.17.0.2:8300} {Suffrage:Voter ID:172.17.0.3:8300 Address:172.17.0.3:8300}]
2017/04/09 05:53:08 [INFO] raft: Added peer 172.17.0.3:8300, starting replication
2017/04/09 05:53:08 [INFO] consul: member 'node2' joined, marking health alive
2017/04/09 05:53:08 [INFO] serf: EventMemberJoin: node2.dc1 172.17.0.3
2017/04/09 05:53:08 [INFO] consul: Handled member-join event for server "node2.dc1" in area "wan"
2017/04/09 05:53:08 [WARN] raft: AppendEntries to {Voter 172.17.0.3:8300 172.17.0.3:8300} rejected, sending older logs (next: 1)
2017/04/09 05:53:08 [INFO] raft: pipelining replication to peer {Voter 172.17.0.3:8300 172.17.0.3:8300}
Node Address Status Type Build Protocol DC
node1 172.17.0.2:8301 alive server 0.8.0 2 dc1
node2 172.17.0.3:8301 alive server 0.8.0 2 dc1
使用
部署完了装诡,那么可以看看怎么用這個東東了。
注冊個服務(wù)
使用HTTP API 注冊個服務(wù),使用[接口API](https://www.consul.io/api/agent/service.html API)調(diào)用
調(diào)用 http://consul:8500/v1/agent/service/register PUT 注冊一個服務(wù)鸦采。request body:
{
"ID": "userServiceId", //服務(wù)id
"Name": "userService", //服務(wù)名
"Tags": [ //服務(wù)的tag宾巍,自定義,可以根據(jù)這個tag來區(qū)分同一個服務(wù)名的服務(wù)
"primary",
"v1"
],
"Address": "127.0.0.1",//服務(wù)注冊到consul的IP渔伯,服務(wù)發(fā)現(xiàn)顶霞,發(fā)現(xiàn)的就是這個IP
"Port": 8000, //服務(wù)注冊consul的PORT,發(fā)現(xiàn)的就是這個PORT
"EnableTagOverride": false,
"Check": { //健康檢查部分
"DeregisterCriticalServiceAfter": "90m",
"HTTP": "http://www.baidu.com", //指定健康檢查的URL锣吼,調(diào)用后只要返回20X选浑,consul都認(rèn)為是健康的
"Interval": "10s" //健康檢查間隔時間,每隔10s吐限,調(diào)用一次上面的URL
}
}
使用curl調(diào)用
curl http://172.17.0.4:8500/v1/agent/service/register -X PUT -i -H "Content-Type:application/json" -d '{
"ID": "userServiceId",
"Name": "userService",
"Tags": [
"primary",
"v1"
],
"Address": "127.0.0.1",
"Port": 8000,
"EnableTagOverride": false,
"Check": {
"DeregisterCriticalServiceAfter": "90m",
"HTTP": "http://www.baidu.com",
"Interval": "10s"
}
}'
OK鲜侥,注冊了一個服務(wù)
發(fā)現(xiàn)個服務(wù)
剛剛注冊了名為userService的服務(wù),我們現(xiàn)在發(fā)現(xiàn)(查詢)下這個服務(wù)
curl http://172.17.0.4:8500/v1/catalog/service/userService
返回的響應(yīng):
[
{
"Address": "172.17.0.4",
"CreateIndex": 880,
"ID": "e6e9a8cb-c47e-4be9-b13e-a24a1582e825",
"ModifyIndex": 880,
"Node": "node3",
"NodeMeta": {},
"ServiceAddress": "127.0.0.1",
"ServiceEnableTagOverride": false,
"ServiceID": "userServiceId",
"ServiceName": "userService",
"ServicePort": 8000,
"ServiceTags": [
"primary",
"v1"
],
"TaggedAddresses": {
"lan": "172.17.0.4",
"wan": "172.17.0.4"
}
}
]
內(nèi)容有了吧诸典,這個就是我們剛剛注冊的服務(wù)的信息,就可以獲取到
服務(wù)的名稱是“userService”
服務(wù)地址是“127.0.0.1”
服務(wù)的端口是“8000”
存儲個K/V
設(shè)置一個值到user/config/connections 內(nèi)容為5
docker exec -t node1 consul kv put user/config/connections 5
獲取特定的值
docker exec -t node1 consul kv get -detailed user/config/connections
值的內(nèi)容為5,還有key等相關(guān)的值
總結(jié)
服務(wù)發(fā)現(xiàn)以及配置共享的簡單樣例展示了下崎苗,詳細(xì)的使用還是需要看官方文檔狐粱,這里只是列舉了一些樣例,用于理解和簡單的使用consul胆数。
Spring Cloud 結(jié)合consul使用
如果是使用spring cloud來使用consul肌蜻,可以查看我的相關(guān)樣例:http://git.oschina.net/buxiaoxia/spring-demo
spring cloud 結(jié)合consul的使用,下一篇文章再進(jìn)行描述吧
相關(guān)文檔連接
CONSUL:https://www.consul.io/
CONSUL HTTP API:https://www.consul.io/api/index.html
CONSUL CLI:https://www.consul.io/docs/commands/info.html
CONSUL Health Checks:https://www.consul.io/docs/agent/checks.html