ETCD V3 Service registration and Discovery go code

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

This article collates the ideas, writes the example (Golang), in order to deepen the ETCD understanding

Basically, the listener is master, service is

1 when the service starts, register its own information with ETCD, that is, register to the services/directory

2 service may be out of the ordinary, need to maintain a TTL (V3 use lease implementation), similar to the heartbeat, hung off, master can be heard

3 master listens to all services under the services/directory, and handles them according to different action (V3 put/delete)

Service Registration

Provide key (service name), value (serviceinfo) for registered

Start after start, perform keeplive (), maintain heartbeat, hang revoke ()

Listen to stop Chan at the same time, equivalent to unregistered

Package Discoveryimport ("GITHUB.COM/COREOS/ETCD/CLIENTV3"    "Context"    " Time"    "Log"    "Encoding/json"    "Errors")//The detail of serviceType ServiceInfostruct{IPstring}type Servicestruct{NamestringInfo serviceinfo Stop chan error Leaseid clientv3. Leaseid Client*CLIENTV3. Client}func NewService (Namestring, Info serviceinfo,endpoints []string) (*Service, error) {CLI, err:=CLIENTV3. New (CLIENTV3. config{endpoints:endpoints, Dialtimeout:2*Time . Second,})ifErr! =Nil {log. Fatal (ERR)returnnil, err}return&Service {name:name, Info:info, Stop:make (chan error), client: CLI,},err}func (s*Service) Start () error {ch, err:=s.keepalive ()ifErr! =Nil {log. Fatal (ERR)returnErr} for {        Select {         CaseERR: = <-S.stop:s.revoke ()returnErr Case<-S.client.ctx (). Done ():returnErrors. New ("Server closed")         CaseKa, OK: = <-Ch:if!OK {log. Println ("keep Alive Channel closed") S.revoke ()returnNil}Else{log. Printf ("Recv reply from service:%s, ttl:%d", S.name, Ka. TTL)}}}}func (S*Service) Stop () {s.stop<-Nil}func (s*service) keepAlive () (<-chan *CLIENTV3. Leasekeepaliveresponse, error) {info:= &s.info Key:="services/"+S.name Value, _:=JSON. Marshal (Info)//Minimum lease TTL is 5-secondRESP, err: = S.client.grant (context. TODO (),5)    ifErr! =Nil {log. Fatal (ERR)returnNil, err} _, Err= S.client.put (context. TODO (), Key,string(value), CLIENTV3. Withlease (resp.id))ifErr! =Nil {log. Fatal (ERR)returnnil, err} S.leaseid=resp.idreturns.client.keepalive (context. TODO (), resp.id)}func (s*Service) Revoke () error {_, err:=S.client.revoke (context. TODO (), S.leaseid)ifErr! =Nil {log. Fatal (Err)} log. Printf ("servide:%s stop\n", S.name)returnErr}

Listener Master

Provide a listening path, start master, add map when put, remove from map when delete

Package Discoveryimport ("GITHUB.COM/COREOS/ETCD/CLIENTV3"    "Context"    "Log"    " Time"    "Encoding/json"    "FMT") Type Masterstruct{PathstringNodes map[string] *Node Client*CLIENTV3. Client}//node is a clientType Nodestruct{ stateBOOLKeystringInfo serviceinfo}func newmaster (endpoints []string, Watchpathstring) (*master,error) {CLI, err:=CLIENTV3. New (CLIENTV3. config{endpoints:endpoints, Dialtimeout:time. Second,})ifErr! =Nil {log. Fatal (ERR)returnNil,err} master:= &Master {path:watchpath, nodes:make (map[string]*Node), CLIENT:CLI,} go master. Watchnodes ()returnMaster,err}func (M*master) AddNode (keystring, Info *serviceinfo) {node:= &node{State:true, Key:key, Info:*info,} m.nodes[node. Key]=node}func getserviceinfo (EV*CLIENTV3. Event) *serviceinfo {info:= &serviceinfo{} ERR:= json. Unmarshal ([]byte(EV. Kv.value), info)ifErr! =Nil {log. PRINTLN (ERR)}returnInfo}func (M*Master) Watchnodes () {rch:=M.client.watch (context. Background (), M.path, CLIENTV3. Withprefix ()) forWRESP: =Range RCH { for_, Ev: =Range Wresp. Events {Switchev. Type { CaseCLIENTV3. Eventtypeput:fmt. Printf ("[%s]%q:%q\n", Ev. Type, Ev. Kv.key, Ev. Kv.value) Info:=getserviceinfo (EV) M.addnode (string(EV. Kv.key), info) CaseCLIENTV3. Eventtypedelete:fmt. Printf ("[%s]%q:%q\n", Ev. Type, Ev. Kv.key, Ev. Kv.value) Delete (M.nodes,string(EV. Kv.key)) }}}}

Service Usage example, disconnect after 20s

Package Mainimport ("fmt" Dis "discovery" "Log" "Time") Func main () {serviceName: = "S-test" serviceinfo: = Dis. Serviceinfo{ip: "192.168.1.26"}s, err: = Dis. NewService (ServiceName, serviceinfo,[]string {"http://192.168.1.17:2379", "http://192.168.1.17:2479", "/HTTP/ 192.168.1.17:2579 ",}) if err! = Nil {log. Fatal (Err)}fmt. Printf ("name:%s, ip:%s\n", S.name, S.info.ip) go func () {time. Sleep (time. SECOND*20) S.stop ()} () S.start ()}

MAster Use example

Package Mainimport ("Log" "Time" "FMT" Dis "discovery") Func main () {m, err: = Dis. Newmaster ([]string{"http://192.168.1.17:2379", "http://192.168.1.17:2479", "http://192.168.1.17:2579",}, " Services/") if err! = Nil {log. Fatal (Err)}for {for k, V: = Range  M.nodes {fmt. Printf ("node:%s, ip=%s\n", K, V.info.ip)}fmt. PRINTF ("Nodes num =%d\n", Len (m.nodes)) time. Sleep (time. Second * 5)}}

Execution result ( need to build ETCD server in advance , can download to GitHub, provide simple startup script at the end)

Go Run Master

Go Run service

ETCD Server startup script (execution Environment CentOS6.5)

#!/bin/Shwork_path=$ (DirName $0) CD./${work_path} #echo $ (PWD) #echo ' Date ' Case$1 inch1) echo-E"[1]start First server\n"./ETCD--name cd0--initial-advertise-peer-urls http://127.0.0.1:2380 \--listen-peer-urls http://127.0.0.1:2380 \--listen-client-urls http://192.168.1.17:2379,http://127.0.0.1: 2379 \--advertise-client-urls http://192.168.1.17:2379,http://127.0.0.1: 2379 \--initial-cluster-token etcd-cluster-1 \  --initial-cluster cd0=http://127.0.0.1:2380,cd1=http://127.0.0.1: 2480,cd2=http://127.0.0.1: 2580 \--initial-cluster-stateNew  ;;2) echo-E"[2]start Second server\n"./ETCD--name CD1--initial-advertise-peer-urls http://127.0.0.1:2480 \--listen-peer-urls http://127.0.0.1:2480 \--listen-client-urls http://192.168.1.17:2479,http://127.0.0.1: 2479 \--advertise-client-urls http://192.168.1.17:2479,http://127.0.0.1: 2479 \--initial-cluster-token etcd-cluster-1 \  --initial-cluster cd0=http://127.0.0.1:2380,cd1=http://127.0.0.1: 2480,cd2=http://127.0.0.1: 2580 \--initial-cluster-stateNew  ;;3) echo-E"[3]start Third server\n"./ETCD--name CD2--initial-advertise-peer-urls http://127.0.0.1:2580 \--listen-peer-urls http://127.0.0.1:2580 \--listen-client-urls http://192.168.1.17:2579,http://127.0.0.1: 2579 \--advertise-client-urls http://192.168.1.17:2579,http://127.0.0.1: 2579 \--initial-cluster-token etcd-cluster-1 \  --initial-cluster cd0=http://127.0.0.1:2380,cd1=http://127.0.0.1: 2480,cd2=http://127.0.0.1: 2580 \--initial-cluster-stateNew  ;;*) echo"Error Paramater";; Esac
View Code

Complete code, please visit git@github.com:moonlong/etcd-discovery.git

Welcome Treatise

Finish!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.