笔记本处理器天梯图-bugtrap dll

remote service error
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