consul
consul用於微服務下的服務治理,主要特點有:服務發現、服務配置、健康檢查、鍵值存儲、安全服務通信、多數據中心等。
什么叫服務治理發現?起初我們的服務比較單一,各服務之間通過接口就能訪問。后面服務越來越復雜出現了分布式,為了不引起單點問題,必然是多服務部署,如果還用原來的方式直接連接,那么在某個服務掛掉或者修改了信息,就會導致連接失敗。如果連接端能夠不去關心具體的服務配置,他只要連接到那個服務,后續的工作由其它服務保證,包括負載均衡、健康檢查等,保證總有可用的連接那就行了,consul就是做這個的,當然,它的功能遠不止這些,這里只是以服務發現為例。
與它同類的東西,還有Eureka、zooKeeper、etcd等也能做這些事,說不上誰好誰壞,看場景挑合適的吧,不過Eureka現在已經閉源了,這個還是建議不要去用這個了。
consul下載
consule的安裝超級簡單,去官方下載地址Download ,找到自已對應系統的壓縮包,解壓后里面就一個文件consul, 將這個文件放到你的PATH中,就能直接用了。
驗證下安裝成功沒有, 看到下面的提示就行了。
$ consul version
Consul v1.7.2
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)
consul的CLI操作
consul提供了cli的命令操作,如啟動代理、鍵值存儲、注冊/注銷服務、加入集群等,這個consul提供的HTTP的API操作也是一樣的,只是這里都是shell的操作。
$ 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
Agent啟動
consul是通過Agent來運行的,Agent又分為Server Agent和Client Agent兩種類型,這兩類型基本上是沒區別的,Server Agent會將服務的消息存儲起來,至少要啟動一個Server Agent,為了防止單點,集群環境中推薦3-5個。
Client Agent主要用於注銷服務、健康檢查及轉發Server Agent的查詢等,它相當於一個代理,所以他必須在集群的每台主機上都要運行。
先看下Agent的常用配置
$ consul agent --help
-
--server 定義運行server agent
-
--data-dir 配置consul數據存儲路徑
-
--bootstrap-expect :期望的server節點數目,consul一直等到指定sever數目的時候才會引導整個集群
-
--bind:該地址用來在集群內部的通訊,集群內的所有節點到地址都必須是可達的,默認是0.0.0.0
-
--node:節點在集群中的名稱,在一個集群中必須是唯一的,默認是該節點的主機名
-
--ui: web的管理ui,查看服務和節點
-
--config-dir:配置文件目錄,所有以.json結尾的文件都會被加載,可以是服務或consul自身的配置
-
--client:提供HTTP、DNS、RPC等服務,默認是127.0.0.1,不對外提供服務,如果需要則改成0.0.0.0
我本地沒有虛擬機,也沒用Docker操作,所以,如果要同時啟動Server和Client的話,我就用的改端口的方式,當然生產環境肯定就沒有這個了,它都是一台機器啟動一個Agent, 這里只是測試用的。
啟動一個Server Agent
$ consul agent --server=true --ui=true --data-dir=/tmp/consul --node=server1 --dev
上面的 --server
表示以server方式,--ui
會開啟一個web ui管理界面, --dev
表示開發者模式,不需要ACL驗證。不然那個web ui的打不開會報沒有權限。
==> Starting Consul agent...
Version: 'v1.7.2'
Node ID: 'f6272369-098a-1412-ed86-6e2076c1e5e4'
Node name: 'server1'
Datacenter: 'dc1' (Segment: '<all>')
Server: true (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
2020-04-01T14:28:52.579+0800 [DEBUG] agent.tlsutil: Update: version=1
2020-04-01T14:28:52.580+0800 [DEBUG] agent.tlsutil: OutgoingRPCWrapper: version=1
2020-04-01T14:28:52.580+0800 [INFO] agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:f6272369-098a-1412-ed86-6e2076c1e5e4 Address:127.0.0.1:8300}]"
2020-04-01T14:28:52.580+0800 [INFO] agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
2020-04-01T14:28:52.581+0800 [INFO] agent.server.serf.wan: serf: EventMemberJoin: server1.dc1 127.0.0.1
2020-04-01T14:28:52.581+0800 [INFO] agent.server.serf.lan: serf: EventMemberJoin: server1 127.0.0.1
2020-04-01T14:28:52.581+0800 [INFO] agent.server: Adding LAN server: server="server1 (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
2020-04-01T14:28:52.581+0800 [INFO] agent.server: Handled event for server in area: event=member-join server=server1.dc1 area=wan
2020-04-01T14:28:52.581+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=tcp
2020-04-01T14:28:52.582+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8600 network=udp
2020-04-01T14:28:52.582+0800 [INFO] agent: Started HTTP server: address=127.0.0.1:8500 network=tcp
2020-04-01T14:28:52.582+0800 [INFO] agent: Started gRPC server: address=127.0.0.1:8502 network=tcp
2020-04-01T14:28:52.582+0800 [INFO] agent: started state syncer
==> Consul agent running!
啟動Client Agent
$ consul agent --data-dir=/tmp/consul_client --join=127.0.0.1:8301 --serf-lan-port=8303 --serf-wan-port=8305 --dns-port=8601 --server-port=8304 --http-port=8503 --server=false --config-dir=./consul.d --enable-script-checks --node=client1
上面有一個--join
表示加入到集群中,寫server agent的地址就行。
config-dir的配置目錄下面一個服務的配置
{
"service":{
"name":"web",
"tags":[
"local"
],
"port":80,
"check":{
"name":"ping",
"args":["/usr/bin/curl","-s", "http://localhost/"],
"interval":"10s"
}
}
}
上面的命令運行后,會啟動一個名字為“web"的服務,並提供健康檢查。
==> Starting Consul agent...
Version: 'v1.7.2'
Node ID: 'e1c8f283-f5c4-27e7-c29c-64666df1c52b'
Node name: 'client1'
Datacenter: 'dc1' (Segment: '')
Server: false (Bootstrap: false)
Client Addr: [127.0.0.1] (HTTP: 8503, HTTPS: -1, gRPC: -1, DNS: 8601)
Cluster Addr: 192.168.0.103 (LAN: 8303, WAN: 8305)
Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false
==> Log data will now stream in as it occurs:
2020-04-01T00:00:49.227+0800 [INFO] agent.client.serf.lan: serf: EventMemberJoin: client1 192.168.0.103
2020-04-01T00:00:49.231+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8601 network=udp
2020-04-01T00:00:49.232+0800 [INFO] agent: Started DNS server: address=127.0.0.1:8601 network=tcp
2020-04-01T00:00:49.232+0800 [INFO] agent: Started HTTP server: address=127.0.0.1:8503 network=tcp
==> Joining cluster...
2020-04-01T00:00:49.232+0800 [INFO] agent: (LAN) joining: lan_addresses=[127.0.0.1:8301]
2020-04-01T00:00:49.233+0800 [WARN] agent.client.memberlist.lan: memberlist: Refuting a dead message (from: client1)
2020-04-01T00:00:49.233+0800 [INFO] agent.client.serf.lan: serf: EventMemberJoin: server1 127.0.0.1
2020-04-01T00:00:49.233+0800 [INFO] agent.client: adding server: server="server1 (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
2020-04-01T00:00:49.233+0800 [INFO] agent: (LAN) joined: number_of_nodes=1
2020-04-01T00:00:49.233+0800 [INFO] agent: Join completed. Initial agents synced with: agent_count=1
2020-04-01T00:00:49.233+0800 [INFO] agent: started state syncer
==> Consul agent running!
2020-04-01T00:00:49.235+0800 [INFO] agent: Synced node info
2020-04-01T00:00:49.235+0800 [INFO] agent: Synced service: service=web
2020-04-01T00:00:53.316+0800 [INFO] agent: Synced check: check=service:web
查看下,啟動的Agent
$ ./consul members
Node Address Status Type Build Protocol DC Segment
server1 127.0.0.1:8301 alive server 1.7.2 2 dc1 <all>
client1 127.0.0.1:8303 alive client 1.7.2 2 dc1 <default>
web管理界面
可以查看服務的定義和節點,訪問[web管理界面](http://127.0.0.1:8500/ui
HTTP API
consul除了提供DNS外,還提供Http的操作,如注冊服務、查看節點、查看服務信息等,一般都是通過API來操作的。
如我上面定義的 "web"服務,通過下面的API查詢,就能得到具體的IP地址和端口,這樣就能直接連到那台服務了。
其它更詳情API操作,可以自已去參照官方的文檔 API
$ curl http://127.0.0.1:8500/v1/catalog/service/web
[
{
"ID": "e1c8f283-f5c4-27e7-c29c-64666df1c52b",
"Node": "client1",
"Address": "127.0.0.1",
"Datacenter": "dc1",
"TaggedAddresses": {
"lan": "127.0.0.1",
"lan_ipv4": "127.0.0.1",
"wan": "127.0.0.1",
"wan_ipv4": "127.0.0.1"
},
"NodeMeta": {
"consul-network-segment": ""
},
"ServiceKind": "",
"ServiceID": "web",
"ServiceName": "web",
"ServiceTags": [
"local"
],
"ServiceAddress": "",
"ServiceWeights": {
"Passing": 1,
"Warning": 1
},
"ServiceMeta": {},
"ServicePort": 80,
"ServiceEnableTagOverride": false,
"ServiceProxy": {
"MeshGateway": {},
"Expose": {}
},
"ServiceConnect": {},
"CreateIndex": 15,
"ModifyIndex": 15
}
]