package EtcdOp
import (
"context"
"fmt"
"github.com/coreos/etcd/clientv3"
"log"
"time"
)
const schema = "etcd"
type RegisterInfomation struct {
Cil *clientv3.Client
}
type EtcdOp interface {
Put(serviceName, value string, ttl int64) error
Get(key string) *clientv3.GetResponse
Close() bool
Watch(target []string, serviceName string)
}
// NewClient
//
// @Description: 实例化RegisterInfomation
// @param target
// @return *RegisterInfomation
func NewClient(target []string) *RegisterInfomation {
//获取endpoints用于实例化etcd对象
cli, err := clientv3.New(
clientv3.Config{
Endpoints: target,
})
if err != nil {
log.Println("实例化对象失败")
}
return &RegisterInfomation{Cil: cli}
}
// Put
//
// @Description: 用于传入etcd,put的时候绑定租约
// @receiver r *RegisterInfomation
// @param serviceName
// @param value
// @param ttl
// @return *RegisterInfomation
func (r *RegisterInfomation) Put(serviceName, value string, ttl int64) error {
//拼接一个key
Key := fmt.Sprintf("%s/%s", schema, serviceName)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
//获取租约
lease := clientv3.NewLease(r.Cil)
leaseresp, err := lease.Grant(ctx, ttl)
if err != nil {
log.Println("获取租约失败", err)
}
fmt.Println("租约获取成功")
//将key和value储存到etcd中 put
_, err = r.Cil.Put(ctx, Key, value, clientv3.WithLease(leaseresp.ID))
cancel()
if err != nil {
return err
}
fmt.Println("put成功")
return nil
}
// Get
//
// @Description: 用于根据key获取value
// @receiver r *RegisterInfomation
// @param cli
// @param key
// @return *clientv3.GetResponse
func (r *RegisterInfomation) Get(key string) *clientv3.GetResponse {
var err error
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
resp, err := r.Cil.Get(ctx, key)
if err != nil {
log.Println("get value fail", err)
}
cancel()
return resp
}
// Close
//
// @Description: 用于关闭client连接
// @receiver r *RegisterInfomation
// @param cli
// @return bool
func (r *RegisterInfomation) Close() bool {
err := r.Cil.Close()
if err != nil {
return true
}
return false
}
// Watch
//
// @Description: 监听服务
// @receiver *RegisterInfomation
// @param cil
// @param key
func (r *RegisterInfomation) Watch(serviceName string) {
Key := fmt.Sprintf("%s/%s", schema, serviceName)
//获取endpoints用于实例化etcd对象
cli, err := clientv3.New(
clientv3.Config{
Endpoints: r.Cil.Endpoints(),
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Println(err)
}
defer cli.Close()
fmt.Println("connect to etcd success")
rec := cli.Watch(context.Background(), Key)
for resp := range rec {
for _, v := range resp.Events {
fmt.Printf("Type: %s Key:%s Value:%s\n", v.Type, v.Kv.Key, v.Kv.Value)
}
}
fmt.Println("watch end!!")
}
因为不怎么喜欢写测试用例,写一个client和一个service测试
客户端
package main
import (
"fmt"
"src/EtcdOp"
)
func main() {
client := EtcdOp.NewClient([]string{"127.0.0.1:2379"})
client.Put("wenzhuhao", "wenzhuhaobaba", 60)
resp := client.Get("etcd/wenzhuhao")
for _, v := range resp.Kvs {
fmt.Printf("%s:%s\n", v.Key, v.Value)
}
}
服务端
package main
import "src/EtcdOp"
func main() {
r := EtcdOp.NewClient([]string{"127.0.0.1:2379"})
r.Watch("wenzhuhao")
}