go+etcd(三): 使用Go实现服务注册

  1. service.go文件
package util

import (
	"context"
	"fmt"
	"github.com/coreos/etcd/clientv3"
	"time"
)

type Service struct {
    
    
	client *clientv3.Client
}

//初始化etcdctl
func NewService() *Service {
    
    
	config:=clientv3.Config{
    
    
		Endpoints:[]string{
    
    "192.168.56.30:23791","192.168.56.30:23792"},
		DialTimeout:10*time.Second,
	}
	client,_:=clientv3.New(config)
	return &Service{
    
    client:client}
}
//注册服务
func(this *Service) RegService(id string,name string,address string) error  {
    
    
	kv:=clientv3.NewKV(this.client)
	key_prefix:="/services/"
	ctx:=context.Background()

	lease:=clientv3.NewLease(this.client)
	leaseRes,err:=lease.Grant(ctx,60) //设置租约(60秒)
	if err!=nil{
    
    
		return err
	}
	//put值
	_,err=kv.Put(ctx,key_prefix+id+"/"+name,address,clientv3.WithLease(leaseRes.ID))
	if err!=nil{
    
    
		return err
	}
	//自动续租
	keepaliveRes,err := lease.KeepAlive(context.TODO(),leaseRes.ID)
	if err!=nil{
    
    
		return err
	}
	//打印续租信息, keepaliveRes是个只读channel
	go lisKeepAlive(keepaliveRes)
	return nil
}

//打印续租信息
func lisKeepAlive(keepaliveRes <-chan *clientv3.LeaseKeepAliveResponse)  {
    
    
	for{
    
    
		select {
    
    
		case ret:=<-keepaliveRes:
			if ret!=nil{
    
    
				fmt.Println("续租成功",time.Now())
			}
		}
	}
}

//反注册服务
func(this *Service) UnregService(id string) error  {
    
    
	kv:=clientv3.NewKV(this.client)
	key_prefix:="/services/"+id
	_,err:=kv.Delete(context.Background(),key_prefix,clientv3.WithPrefix())
	return err
}
  1. p1.go
package main

import (
	"context"
	"fmt"
	"github.com/gorilla/mux"
	"goetcd/util"
	"log"
	"net/http"
	"os"
	"os/signal"
	"strconv"
	"syscall"
)

func main()  {
    
    
	//路由
	router:=mux.NewRouter()

	router.HandleFunc("/product/{id:\\d+}", func(writer http.ResponseWriter, request *http.Request) {
    
    
		vars:=mux.Vars(request)
		str:="get product ByID:"+vars["id"]
		writer.Write([]byte(str))
	})
	//初始化etcdctl
	service:=util.NewService()
	serviceID:="p1"	//服务ID
	serviceName:="productservice"	//服务名
	serviceAddr:="192.168.16.30"		//服务地址
	servicePort:=8081	//服务端口

	//错误channel
	errChan:=make(chan error)

	//初始化http
	httpServer:=&http.Server{
    
    
		Addr:":"+strconv.Itoa(servicePort),
		Handler:router,
	}
	 go(func() {
    
    
	 	//注册服务
		 err:=service.RegService(serviceID,serviceName,serviceAddr+":"+strconv.Itoa(servicePort))
		 if err!=nil{
    
    
		 	errChan<-err
		 	return
		 }
		 //开启http服务
		 err=httpServer.ListenAndServe()
		 if err!=nil{
    
    
			errChan<-err
			return
		 }
	 })()

	//信号监听
	go(func(){
    
    
		 sig:=make(chan os.Signal)
		 signal.Notify(sig,syscall.SIGINT,syscall.SIGTERM)
		 errChan<-fmt.Errorf("%s",<-sig)
	})()

	getErr:=<-errChan
	err:=service.UnregService(serviceID)//反注册
	if err!=nil{
    
    
		fmt.Println(err)
	}
	//可以执行一些 回收工作,譬如关闭数据库
	err=httpServer.Shutdown(context.Background())
	if err!=nil{
    
    
		log.Fatal(err)
	}
    log.Fatal(getErr)
}
  1. 启用p1.go, 进入etcd容器,获取键值成功
/usr/bin # ./etcdctl get /services/p1/productservice
/services/p1/productservice
192.168.16.30:8081

猜你喜欢

转载自blog.csdn.net/qq_36453564/article/details/108264582