内容简介:从2016年开始接触微服务的时候就使用consul,当初只知道其特别方便,是一款不错的服务注册与发现工具。至于其部署架构,实现原理都没有深入去了解过,就如同年少读书不求甚解。最近,在着手搞微服务治理,服务治理与发现这块正好选型consul,这才详细的琢磨了下其代码,也对其原理有了一定的认识。下面就听我就徐徐道来……下面是consul官方给出的一张架构图,我们先来理解一下。
从2016年开始接触微服务的时候就使用consul,当初只知道其特别方便,是一款不错的服务注册与发现工具。至于其部署架构,实现原理都没有深入去了解过,就如同年少读书不求甚解。最近,在着手搞微服务治理,服务治理与发现这块正好选型consul,这才详细的琢磨了下其代码,也对其原理有了一定的认识。下面就听我就徐徐道来……
架构介绍
下面是consul官方给出的一张架构图,我们先来理解一下。
首先,从架构上,图片被两个datacenter分成了上下两部分;但这两部分又并不是完全隔离的,他们之间通过WAN GOSSIP在Internet上交互报文。因此,我们了解到consul是可以支持多个数据中心之间基于WAN来做同步的。
再看单个datacenter内部,节点被划分为两种颜色,其中红色为server,紫色为client。它们之间通过GRPC通信(主要用于业务数据)。除此之外,server和client之间,还有一条LAN GOSSIP通信,这是用于当LAN内部发生了拓扑变化时,存活的节点们能够及时感知,比如server节点down掉后,client就会触发将对应server节点从可用列表中剥离出去。
当然,server与server之间,client与client之间,client与server之间,在同一个datacenter中的所有consul agent会组成一个LAN网络(当然它们之间也可以按照区域划分segment),当LAN网中有任何角色变动,或者有用户自定义的event产生的时候,其他节点就会感知到,并触发对应的预置操作。
所有的server节点共同组成了一个集群,他们之间运行raft协议,通过共识仲裁选举出leader。所有的业务数据都通过leader写入到集群中做持久化,当有半数以上的节点存储了该数据后,server集群才会返回ACK,从而保障了数据的强一致性。当然,server数量大了之后,也会影响写数据的效率。所有的follower会跟随leader的脚步,保障其有最新的数据副本。
同一个consul agent程序,通过启动的时候指定不同的参数来运行server或client模式。这两种模式下,各自所负责的事务具体如下。
Server节点
- 参与共识仲裁(raft)
- 存储群集状态(日志存储)
- 处理查询
- 维护与周边(LAN/WAN)各节点关系
Agent节点
- 负责通过该节点注册到consul的微服务的健康检查
- 将客户端注册请求以及查询转化为对server的RPC请求
- 维护与周边(LAN/WAN)各节点关系
服务端口
端口 | 作用 |
---|---|
8300 | RPC exchanges |
8301 | LAN GOSSIP |
8302 | WAN GOSSIP |
8400 | RPC exchanges by the CLI |
8500 | Used for HTTP API and web interface |
8600 | Used for DNS server |
实现原理
纵观consul的实现,其核心在于两点:
- 集群内节点间信息的高效同步机制,其保障了拓扑变动以及控制信号的及时传递;
- server集群内日志存储的强一致性。
它们主要基于以下两个协议来实现:
- 使用gossip协议在集群内传播信息
- 使用raft协议来保障日志的一致性
Serf
serf是hashicorp基于GOSSIP协议来实现的一个用于分布式集群成员管理,失败检测以及编排的工具,当前最新版本为v0.8.1。有兴趣的朋友可以到这个链接具体了解 hashicorp serf ,下面我来简单介绍一下其功能。
集群管理
这台机器上有两个IP地址,一个是172.20.20.10,另一个为172.20.20.10。我准备启动两个serf agent进程,分别绑定到不同的两个IP地址上,各自叫做agent-one和agent-two。
由于它们启动之后,相互之间是不知道彼此的,我通过执行 serf join
来把它们组成一个LAN serf。这样它们就可以彼此检测到彼此,通过查看serf members可以看到所有的节点以及其健康状况。
$ serf agent -node=agent-one -bind=172.20.20.10 $ serf agent -node=agent-two -bind=172.20.20.11 $ serf join 172.20.20.11 $ serf members agent-one 172.20.20.10:7946 alive agent-two 172.20.20.11:7946 alive
事件响应
在前面的步骤中,我们将两个serf进程加入到了同一个LAN中,接下来我们将进行一些更加激动人心的实践。接下来,我们创建了一个脚本(handler.sh),大致内容为:当脚本被调用的时候,会打印出一些具体的信息。然后,我们在启动serf agent的时候,通过参数将该脚本传递给serf agent。这样当收该serf节点收到event时,就会调用用户指定的handler(即执行脚本)。
$ cat handler.sh #!/bin/bash echo echo "New event: ${SERF_EVENT}. Data follows..." while read line; do printf "${line}\n" done $ serf agent -log-level=debug -event-handler=handler.sh
发送自定义event
$ serf event hello-there
Event类型
serf指定了下面这些类型的event,各自的作用如下所示:
member-join One or more members have joined the cluster. member-leave One or more members have gracefully left the cluster. member-failed One or more members have failed, meaning that they did not properly respond to ping requests. member-update One or more members have updated, likely to update the associated tags member-reap Serf has removed one or more members from its list of members. This means a failed node exceeded the reconnect_timeout, or a left node reached the tombstone_timeout. user A custom user event, covered later in this guide. query A query event, covered later in this guide
Raft
由于介绍raft协议的文章已经比较多,我这里就不在详述。这里重点分析一下在consul中,raft协议运作的一些实践和日志。
节点状态变更
- 在节点数达到bootstrap-expect的数时,开始启用raft选举
- 在节点数超过bootstrap-expect数时,其他节点为follower
- 在leader被干掉后,raft如果判断到节点数依然大于等于bootstrap-expect时,重新选举
- 逐一干掉节点,当节点数少于bootstrap-expect时,raft协议不再选举,将维持先前的状态。
Raft选举日志分析
# 选举日志信息 (bootstrap) ==> Starting Consul agent... bootstrap_expect > 0: expecting 3 servers ==> Consul agent running! Version: 'v1.4.0' Node ID: 'f217ca95-e83c-9a1f-9e87-3b5c1f5a82a3' Node name: '42ddc7aa3bb6' Datacenter: 'dc1' (Segment: '<all>') Server: true (Bootstrap: false) Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: -1, DNS: 8600) Cluster Addr: 172.17.0.2 (LAN: 8301, WAN: 8302) Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false ==> Log data will now stream in as it occurs: 2018/12/03 07:21:34 [INFO] raft: Initial configuration (index=0): [] 2018/12/03 07:21:34 [INFO] serf: EventMemberJoin: 42ddc7aa3bb6.dc1 172.17.0.2 2018/12/03 07:21:34 [INFO] serf: EventMemberJoin: 42ddc7aa3bb6 172.17.0.2 2018/12/03 07:21:34 [INFO] raft: Node at 172.17.0.2:8300 [Follower] entering Follower state (Leader: "") 2018/12/03 07:21:34 [INFO] consul: Adding LAN server 42ddc7aa3bb6 (Addr: tcp/172.17.0.2:8300) (DC: dc1) 2018/12/03 07:21:34 [INFO] consul: Handled member-join event for server "42ddc7aa3bb6.dc1" in area "wan" 2018/12/03 07:21:34 [INFO] agent: Started DNS server 127.0.0.1:8600 (tcp) 2018/12/03 07:21:34 [INFO] agent: Started DNS server 127.0.0.1:8600 (udp) 2018/12/03 07:21:34 [INFO] agent: Started HTTP server on 127.0.0.1:8500 (tcp) 2018/12/03 07:21:34 [INFO] agent: started state syncer 2018/12/03 07:21:34 [INFO] agent: Retry join LAN is supported for: aliyun aws azure digitalocean gce k8s os packet scaleway softlayer triton vsphere 2018/12/03 07:21:34 [INFO] agent: Joining LAN cluster... 2018/12/03 07:21:34 [INFO] agent: (LAN) joining: [172.17.0.2] 2018/12/03 07:21:34 [INFO] agent: (LAN) joined: 1 Err: <nil> 2018/12/03 07:21:34 [INFO] agent: Join LAN completed. Synced with 1 initial agents # node数量没有达到,无法开始选举 2018/12/03 07:21:41 [ERR] agent: failed to sync remote state: No cluster leader 2018/12/03 07:21:43 [WARN] raft: no known peers, aborting election 2018/12/03 07:21:54 [INFO] serf: EventMemberJoin: 4eb2b75f454a 172.17.0.3 2018/12/03 07:21:54 [INFO] consul: Adding LAN server 4eb2b75f454a (Addr: tcp/172.17.0.3:8300) (DC: dc1) 2018/12/03 07:21:54 [INFO] serf: EventMemberJoin: 4eb2b75f454a.dc1 172.17.0.3 2018/12/03 07:21:54 [INFO] consul: Handled member-join event for server "4eb2b75f454a.dc1" in area "wan" 2018/12/03 07:21:58 [INFO] serf: EventMemberJoin: b603f61d1449 172.17.0.4 2018/12/03 07:21:58 [INFO] consul: Adding LAN server b603f61d1449 (Addr: tcp/172.17.0.4:8300) (DC: dc1) # node数量达到,开始选举 2018/12/03 07:21:58 [INFO] consul: Found expected number of peers, attempting bootstrap: 172.17.0.2:8300,172.17.0.3:8300,172.17.0.4:8300 2018/12/03 07:21:58 [INFO] serf: EventMemberJoin: b603f61d1449.dc1 172.17.0.4 2018/12/03 07:21:58 [INFO] consul: Handled member-join event for server "b603f61d1449.dc1" in area "wan" 2018/12/03 07:22:03 [WARN] raft: Heartbeat timeout from "" reached, starting election # 状态迁移 2018/12/03 07:22:03 [INFO] raft: Node at 172.17.0.2:8300 [Candidate] entering Candidate state in term 2 # 获胜 2018/12/03 07:22:03 [INFO] raft: Election won. Tally: 2 2018/12/03 07:22:03 [INFO] raft: Node at 172.17.0.2:8300 [Leader] entering Leader state 2018/12/03 07:22:03 [INFO] raft: Added peer 5b0b26fb-5e62-c390-0ced-b80e0f3293ef, starting replication 2018/12/03 07:22:03 [INFO] raft: Added peer 3844affd-9b4e-ad3d-84f3-25fb77806e7c, starting replication 2018/12/03 07:22:03 [INFO] consul: cluster leadership acquired 2018/12/03 07:22:03 [INFO] consul: New leader elected: 42ddc7aa3bb6 2018/12/03 07:22:03 [WARN] raft: AppendEntries to {Voter 3844affd-9b4e-ad3d-84f3-25fb77806e7c 172.17.0.4:8300} rejected, sending older logs (next: 1) 2018/12/03 07:22:03 [WARN] raft: AppendEntries to {Voter 5b0b26fb-5e62-c390-0ced-b80e0f3293ef 172.17.0.3:8300} rejected, sending older logs (next: 1) 2018/12/03 07:22:03 [INFO] raft: pipelining replication to peer {Voter 3844affd-9b4e-ad3d-84f3-25fb77806e7c 172.17.0.4:8300} 2018/12/03 07:22:03 [INFO] raft: pipelining replication to peer {Voter 5b0b26fb-5e62-c390-0ced-b80e0f3293ef 172.17.0.3:8300} 2018/12/03 07:22:03 [INFO] consul: member '42ddc7aa3bb6' joined, marking health alive 2018/12/03 07:22:03 [INFO] consul: member '4eb2b75f454a' joined, marking health alive 2018/12/03 07:22:03 [INFO] consul: member 'b603f61d1449' joined, marking health alive ==> Failed to check for updates: Get https://checkpoint-api.hashicorp.com/v1/check/consul?arch=amd64&os=linux&signature=2ba01aad-86ad-32b1-2cff-dc77537fa0dd&version=1.4.0: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers) 2018/12/03 07:22:05 [INFO] agent: Synced node info 2018/12/03 07:27:25 [INFO] serf: EventMemberJoin: 212149acfdcd 172.17.0.5 2018/12/03 07:27:25 [INFO] consul: Adding LAN server 212149acfdcd (Addr: tcp/172.17.0.5:8300) (DC: dc1) # 添加的新节点为novoter角色,无法参与选举 2018/12/03 07:27:25 [INFO] raft: Updating configuration with AddNonvoter (45c059ba-bd5c-5a00-f7d6-e490324e7b52, 172.17.0.5:8300) to [{Suffrage:Voter ID:f217ca95-e83c-9a1f-9e87-3b5c1f5a82a3 Address:172.17.0.2:8300} {Suffrage:Voter ID:5b0b26fb-5e62-c390-0ced-b80e0f3293ef Address:172.17.0.3:8300} {Suffrage:Voter ID:3844affd-9b4e-ad3d-84f3-25fb77806e7c Address:172.17.0.4:8300} {Suffrage:Nonvoter ID:45c059ba-bd5c-5a00-f7d6-e490324e7b52 Address:172.17.0.5:8300}] 2018/12/03 07:27:25 [INFO] serf: EventMemberJoin: 212149acfdcd.dc1 172.17.0.5 2018/12/03 07:27:25 [INFO] consul: Handled member-join event for server "212149acfdcd.dc1" in area "wan" 2018/12/03 07:27:25 [INFO] raft: Added peer 45c059ba-bd5c-5a00-f7d6-e490324e7b52, starting replication 2018/12/03 07:27:25 [WARN] raft: AppendEntries to {Nonvoter 45c059ba-bd5c-5a00-f7d6-e490324e7b52 172.17.0.5:8300} rejected, sending older logs (next: 1) 2018/12/03 07:27:25 [INFO] consul: member '212149acfdcd' joined, marking health alive 2018/12/03 07:27:25 [INFO] raft: pipelining replication to peer {Nonvoter 45c059ba-bd5c-5a00-f7d6-e490324e7b52 172.17.0.5:8300} 2018/12/03 07:27:28 [INFO] serf: EventMemberJoin: edb64d232050 172.17.0.6 2018/12/03 07:27:28 [INFO] consul: Adding LAN server edb64d232050 (Addr: tcp/172.17.0.6:8300) (DC: dc1) # 添加的新节点为novoter角色,无法参与选举 2018/12/03 07:27:28 [INFO] raft: Updating configuration with AddNonvoter (46ebd85c-5e96-f9bd-81e4-0a82d3b405c7, 172.17.0.6:8300) to [{Suffrage:Voter ID:f217ca95-e83c-9a1f-9e87-3b5c1f5a82a3 Address:172.17.0.2:8300} {Suffrage:Voter ID:5b0b26fb-5e62-c390-0ced-b80e0f3293ef Address:172.17.0.3:8300} {Suffrage:Voter ID:3844affd-9b4e-ad3d-84f3-25fb77806e7c Address:172.17.0.4:8300} {Suffrage:Nonvoter ID:45c059ba-bd5c-5a00-f7d6-e490324e7b52 Address:172.17.0.5:8300} {Suffrage:Nonvoter ID:46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 Address:172.17.0.6:8300}] 2018/12/03 07:27:28 [INFO] serf: EventMemberJoin: edb64d232050.dc1 172.17.0.6 2018/12/03 07:27:28 [INFO] consul: Handled member-join event for server "edb64d232050.dc1" in area "wan" 2018/12/03 07:27:28 [INFO] raft: Added peer 46ebd85c-5e96-f9bd-81e4-0a82d3b405c7, starting replication 2018/12/03 07:27:28 [INFO] consul: member 'edb64d232050' joined, marking health alive 2018/12/03 07:27:28 [WARN] raft: AppendEntries to {Nonvoter 46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 172.17.0.6:8300} rejected, sending older logs (next: 1) 2018/12/03 07:27:28 [INFO] raft: pipelining replication to peer {Nonvoter 46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 172.17.0.6:8300} 2018/12/03 07:27:43 [INFO] autopilot: Promoting Server (ID: "45c059ba-bd5c-5a00-f7d6-e490324e7b52" Address: "172.17.0.5:8300") to voter 2018/12/03 07:27:43 [INFO] raft: Updating configuration with AddStaging (45c059ba-bd5c-5a00-f7d6-e490324e7b52, 172.17.0.5:8300) to [{Suffrage:Voter ID:f217ca95-e83c-9a1f-9e87-3b5c1f5a82a3 Address:172.17.0.2:8300} {Suffrage:Voter ID:5b0b26fb-5e62-c390-0ced-b80e0f3293ef Address:172.17.0.3:8300} {Suffrage:Voter ID:3844affd-9b4e-ad3d-84f3-25fb77806e7c Address:172.17.0.4:8300} {Suffrage:Voter ID:45c059ba-bd5c-5a00-f7d6-e490324e7b52 Address:172.17.0.5:8300} {Suffrage:Nonvoter ID:46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 Address:172.17.0.6:8300}] 2018/12/03 07:27:43 [INFO] autopilot: Promoting Server (ID: "46ebd85c-5e96-f9bd-81e4-0a82d3b405c7" Address: "172.17.0.6:8300") to voter 2018/12/03 07:27:43 [INFO] raft: Updating configuration with AddStaging (46ebd85c-5e96-f9bd-81e4-0a82d3b405c7, 172.17.0.6:8300) to [{Suffrage:Voter ID:f217ca95-e83c-9a1f-9e87-3b5c1f5a82a3 Address:172.17.0.2:8300} {Suffrage:Voter ID:5b0b26fb-5e62-c390-0ced-b80e0f3293ef Address:172.17.0.3:8300} {Suffrage:Voter ID:3844affd-9b4e-ad3d-84f3-25fb77806e7c Address:172.17.0.4:8300} {Suffrage:Voter ID:45c059ba-bd5c-5a00-f7d6-e490324e7b52 Address:172.17.0.5:8300} {Suffrage:Voter ID:46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 Address:172.17.0.6:8300}]
源码架构
TODO
操作实践
介绍consul agent的配置参数,以及各种使用场景下的命令。
consul agent参数
-advertise 通知展现地址用来改变我们给集群中的其他节点展现的地址,一般情况下-bind地址就是展现地址 -bootstrap 用来控制一个server是否在bootstrap模式,在一个datacenter中只能有一个server处于bootstrap模式,当一个server处于bootstrap模式时,可以自己选举为raft leader。 -bootstrap-expect 在一个datacenter中期望提供的server节点数目,当该值提供的时候,consul一直等到达到指定sever数目的时候才会引导整个集群,该标记不能和bootstrap公用 -bind 该地址用来在集群内部的通讯,集群内的所有节点到地址都必须是可达的,默认是0.0.0.0 -client consul绑定在哪个client地址上,这个地址提供HTTP、DNS、RPC等服务,默认是127.0.0.1 -config-file 明确的指定要加载哪个配置文件 -config-dir 配置文件目录,里面所有以.json结尾的文件都会被加载 -data-dir 提供一个目录用来存放agent的状态,所有的agent允许都需要该目录,该目录必须是稳定的,系统重启后都继续存在 -dc 该标记控制agent允许的datacenter的名称,默认是dc1 -encrypt 指定secret key,使consul在通讯时进行加密,key可以通过consul keygen生成,同一个集群中的节点必须使用相同的key -join 加入一个已经启动的agent的ip地址,可以多次指定多个agent的地址。如果consul不能加入任何指定的地址中,则agent会启动失败,默认agent启动时不会加入任何节点。 -retry-join 和join类似,但是允许你在第一次失败后进行尝试。 -retry-interval 两次join之间的时间间隔,默认是30s -retry-max 尝试重复join的次数,默认是0,也就是无限次尝试 -log-level consul agent启动后显示的日志信息级别。默认是info,可选:trace、debug、info、warn、err。 -node 节点在集群中的名称,在一个集群中必须是唯一的,默认是该节点的主机名 -protocol consul使用的协议版本 -rejoin 使consul忽略先前的离开,在再次启动后仍旧尝试加入集群中。 -server 定义agent运行在server模式,每个集群至少有一个server,建议每个集群的server不要超过5个 -syslog 开启系统日志功能,只在linux/osx上生效 -ui-dir 提供存放web ui资源的路径,该目录必须是可读的 -pid-file 提供一个路径来存放pid文件,可以使用该文件进行SIGINT/SIGHUP(关闭/更新)agent
常用命令
开发模式
最简单,可以用于本地微服务开发的时候,零时做服务注册与发现工具。请注意的是,开发模式下,consul不会做配置的持久化,当consul服务终止时,之前注册的服务和K/V都会随之丢失!
docker run -d --name=dev-consul -e CONSUL_BIND_INTERFACE=eth0 consul
server模式
docker run -d --net=host -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' consul agent -server -bind=<external ip> -retry-join=<root agent ip> -bootstrap-expect=<number of server agents>
- 启动server
docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' consul agent -server -retry-join=172.17.0.2 -bootstrap-expect=3
client模式
- 启动client
docker run -d -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt": true}' consul agent -retry-join=172.17.0.2
- 暴露dns
docker run -d --net=host -e 'CONSUL_ALLOW_PRIVILEGED_PORTS=' consul -dns-port=53 -recursor=8.8.8.8
- 查询
docker exec -t dev-consul consul members dig @localhost -p 8600 consul.service.consul
集群部署实践
下面是部署两个server和一个agent的实例
-
s1: 10.200.204.104
./consul agent -server -bootstrap-expect 1 -data-dir /etc/consul/data -node=s1 -bind=10.200.204.104 -ui -rejoin -config-dir=/etc/consul/conf -client 0.0.0.0
-
s2: 10.200.204.48
./consul agent -server -bootstrap-expect 1 -data-dir /etc/consul/data -node=s2 -bind=10.200.204.48 -ui -rejoin -config-dir=/etc/consul/conf -client 0.0.0.0 -retry-join=10.200.204.104
-
c1: 10.200.204.133
./consul agent -node=c1 -bind=10.200.204.133 -data-dir /etc/consul/data -ui -rejoin -config-dir=/etc/consul/conf -client 0.0.0.0 -retry-join=10.200.204.48
查看raft角色
# consul operator raft list-peers Node ID Address State Voter RaftProtocol b603f61d1449 3844affd-9b4e-ad3d-84f3-25fb77806e7c 172.17.0.4:8300 follower true 3 212149acfdcd 45c059ba-bd5c-5a00-f7d6-e490324e7b52 172.17.0.5:8300 follower true 3 edb64d232050 46ebd85c-5e96-f9bd-81e4-0a82d3b405c7 172.17.0.6:8300 leader true 3
注册服务到consul
cat << EOF >> payload.json { "Datacenter": "dc1", "ID": "40e4a748-2192-161a-0510-9bf59fe950b5", "Node": "foobar", "Address": "192.168.10.10", "TaggedAddresses": { "lan": "192.168.10.10", "wan": "10.0.10.10" }, "NodeMeta": { "somekey": "somevalue" }, "Service": { "ID": "redis1", "Service": "redis", "Tags": [ "primary", "v1" ], "Address": "127.0.0.1", "Meta": { "redis_version": "4.0" }, "Port": 8000 }, "Check": { "Node": "foobar", "CheckID": "service:redis1", "Name": "Redis health check", "Notes": "Script based health check", "Status": "passing", "ServiceID": "redis1", "Definition": { "TCP": "localhost:8888", "Interval": "5s", "Timeout": "1s", "DeregisterCriticalServiceAfter": "30s" } }, "SkipNodeUpdate": false } EOF
一般不推荐使用catalog注册,而是使用agent来注册,这里只是测试用。
curl --request PUT --data @payload.json http://127.0.0.1:8500/v1/catalog/register
配置文件注册
直接将以下json文件保存后存放到 --config-dir
目录下,重启consul服务
{ "service":{ "id": "jetty", "name": "jetty", "address": "14.215.177.38", "port": 80, "tags": ["dev"], "checks": [ { "http": "http://14.215.177.38:80/", "interval": "5s" } ] } }
会发现,在哪一个client节点上注册的服务,对应client节点就会负责做healthcheck,也就意味着,这个节点非常重要,如果做不好高可用,所有注册到上面的服务都有被deregisterd的风险。
API 注册
curl -X PUT -d '{"id": "ljchen","name": "ljchen","address": "14.215.177.38","port": 80,"tags": ["dev"],"checks": [{"http": "http://14.215.177.38:80/","interval": "5s"}]}' http://127.0.0.1:8500/v1/agent/service/register
查询consul中的服务
curl http://127.0.0.1:8500/v1/catalog/service/redis?tag=v1
以上所述就是小编给大家介绍的《Consul原理解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Unity Shader入门精要
冯乐乐 / 人民邮电出版社 / 2016-5-1 / CNY 69.00
本书不仅要教会读者如何使用Unity Shader,更重要的是要帮助读者学习Unity中的一些渲染机制以及如何使用Unity Shader实现各种自定义的渲染效果,希望这本书可以为读者打开一扇新的大门,让读者离制作心目中杰出游戏的心愿更近一步。 本书的主要内容为:第1章讲解了学习Unity Shader应该从哪里着手;第2章讲解了现代GPU是如何实现整个渲染流水线的,这对理解Shader的工......一起来看看 《Unity Shader入门精要》 这本书的介绍吧!