笔记本处理器天梯图-bugtrap dll
![remote service error](/uploads/image/0078.jpg)
2023年4月3日发(作者:mp4分割器)
golang⽤etcd实现服务注册和发现
系统中实现服务注册与发现所需的基本功能有
服务注册:同⼀service的所有节点注册到相同⽬录下,节点启动后将⾃⼰的信息注册到所属服务的⽬录中。
健康检查:服务节点定时发送⼼跳,注册到服务⽬录中的信息设置⼀个较短的TTL,运⾏正常的服务节点每隔⼀段时间会去更新信息的
TTL。
服务发现:通过名称能查询到服务提供外部访问的IP和端⼝号。⽐如⽹关代理服务时能够及时的发现服务中新增节点、丢弃不可⽤的
服务节点,同时各个服务间也能感知对⽅的存在。
在分布式系统中,如何管理节点间的状态⼀直是⼀个难题,etcd是由开发并维护的,它使⽤Go语⾔编写,并通过Raft⼀致性算法处理⽇
志复制以保证强⼀致性。etcd像是专门为集群环境的服务发现和注册⽽设计,它提供了数据TTL失效、数据改变监视、多值、⽬录监听、
分布式锁原⼦操作等功能,可以⽅便的跟踪并管理集群节点的状态。
我们写两个Demo程序,⼀个服务充当service,⼀个客户端程序充当⽹关代理。服务运⾏后会去etcd以⾃⼰服务名命名的⽬录中注册服
务节点,并定时续租(更新TTL)。客户端从etcd查询服务⽬录中的节点信息代理服务的请求,并且会在协程中实时监控服务⽬录中的变
化,维护到⾃⼰的服务节点信息列表中。
导⼊包:/etcd/clientv3
//将服务注册到etcd上
funcRegisterServiceToETCD(ServiceTargetstring,valuestring){
dir=ght(ServiceTarget,"/")+"/"
client,err:=({
Endpoints:[]string{"localhost:2379"},
DialTimeout:5*,
})
iferr!=nil{
panic(err)
}
kv:=(client)
lease:=se(client)
D=0
for{
ifcurLeaseId==0{
leaseResp,err:=((),10)
iferr!=nil{
panic(err)
}
key:=ServiceTarget+f("%d",)
if_,err:=((),key,value,ase());err!=nil{
panic(err)
}
curLeaseId=
}else{
//续约租约,如果租约已经过期将curLeaseId复位到0重新⾛创建租约的逻辑
if_,err:=iveOnce((),curLeaseId);err==seNotFound{
curLeaseId=0
continue
}
}
(on(1)*)
}
}
typeHelloServicestruct{}
func(p*HelloService)Hello(requeststring,reply*string)error{
*reply="hello:"+request
returnnil
}
varserviceTarget="Hello"
varport=":1234"
varhost="remote_host"//伪代码
funcmain(){
erName("HelloService",new(HelloService))
listener,err:=("tcp",port)
iferr!=nil{
("ListenTCPerror:",err)
}
conn,err:=()
iferr!=nil{
("Accepterror:",err)
}
goRegisterServiceToETCD(serviceTarget,host+port)
onn(conn)
}
⽹关通过etcd获取到服务⽬录下的所有节点的信息,将他们初始化到⾃⾝维护的可访问服务节点列表中。然后使⽤Watch机制监听etcd上
服务对应的⽬录的更新,根据通道发送过来的PUT和DELETE事件来增加和删除服务的可⽤节点列表。
varserviceTarget="Hello"
typeremoteServicestruct{
namestring
nodesmap[string]string
}
//获取服务⽬录下所有key初始化到服务的可⽤节点列表中
funcgetService()*remoteService{
service=&remoteService{
name:serviceTarget
}
kv:=(etcdClient)
rangeResp,err:=((),,efix())
iferr!=nil{
panic(err)
}
()
for_,kv:={
[string()]=string()
}
()
gowatchServiceUpdate(etcdClient,service)
}
//监控服务⽬录下的事件
funcwatchServiceUpdate(,service*remoteService){
watcher:=cher(client)
//Watch服务⽬录下的更新
watchChan:=((),,efix())
forwatchResp:=rangewatchChan{
for_,event:={
()
switch(){
://PUT事件,⽬录下有了新key
[string()]=string()
://DELETE事件,⽬录中有key被删掉(Lease过期,key也会被删掉)
delete(,string())
}
()
}
}
}
funcmain(){
client,err:=({
Endpoints:[]string{"remote_host:2379"},
DialTimeout:5*,
})
service:=getService(client)//获取服务的可⽤节点
......
//每次有请求过来从服务节点中选取⼀个连接,然后给节点发送请求
rpcClient,_=("tcp",[i])
varreplystring
("",&reply)
......
}
除了上⾯说的客户端或者⽹关发现系统中的已存服务外,系统中的各个服务之间也需要感知到其他⾓⾊的存在,服务间的发现⽅法与上⾯的
例⼦类似,每个服务都能作为客户端在etcd中发现其他服务的存在。
更多推荐
remote service error
发布评论