github.com/ppphp/yayagf@v0.0.1/pkg/etcd/etcd.go (about) 1 package etcd 2 3 import ( 4 "context" 5 "fmt" 6 "time" 7 8 "go.etcd.io/etcd/api/v3/mvccpb" 9 "go.etcd.io/etcd/api/v3/v3rpc/rpctypes" 10 clientv3 "go.etcd.io/etcd/client/v3" 11 "go.uber.org/atomic" 12 ) 13 14 func RegisterService(context context.Context, etcdaddrs []string, serviceName string) error { 15 c, err := clientv3.New(clientv3.Config{ 16 Endpoints: etcdaddrs, 17 DialTimeout: 5 * time.Second, 18 }) 19 if err != nil { 20 return err 21 } 22 23 kv := clientv3.NewKV(c) 24 lease := clientv3.NewLease(c) 25 var curLeaseId clientv3.LeaseID = 0 26 timer := time.NewTicker(1 * time.Second) 27 28 go func() { 29 for { 30 select { 31 case <-timer.C: 32 if curLeaseId == 0 { 33 leaseResp, err := lease.Grant(context, 10) 34 if err != nil { 35 panic(err) 36 } 37 38 key := "/services/" + serviceName + "/" + fmt.Sprintf("%d", leaseResp.ID) 39 if _, err := kv.Put(context, key, value, clientv3.WithLease(leaseResp.ID)); err != nil { 40 panic(err) 41 } 42 curLeaseId = leaseResp.ID 43 } else { 44 // 续约租约,如果租约已经过期将curLeaseId复位到0重新走创建租约的逻辑 45 if _, err := lease.KeepAliveOnce(context, curLeaseId); err == rpctypes.ErrLeaseNotFound { 46 curLeaseId = 0 47 continue 48 } 49 } 50 case <-context.Done(): 51 return 52 } 53 } 54 defer c.Close() 55 }() 56 57 return nil 58 } 59 60 func GetService(context context.Context, etcdaddrs []string, serviceName string) *remoteService { 61 c, err := clientv3.New(clientv3.Config{ 62 Endpoints: etcdaddrs, 63 DialTimeout: 5 * time.Second, 64 }) 65 if err != nil { 66 return err 67 } 68 kv := clientv3.NewKV(c) 69 rangeResp, err := kv.Get(context, "/services/"+serviceName, clientv3.WithPrefix()) 70 if err != nil { 71 panic(err) 72 } 73 74 service.mutex.Lock() 75 for _, kv := range rangeResp.Kvs { 76 service.nodes[string(kv.Key)] = string(kv.Value) 77 } 78 service.mutex.Unlock() 79 watcher := clientv3.NewWatcher(client) 80 watchChan := watcher.Watch(context, service.name, clientv3.WithPrefix()) 81 82 go func() { 83 for watchResp := range watchChan { 84 for _, event := range watchResp.Events { 85 service.mutex.Lock() 86 switch event.Type { 87 case mvccpb.PUT: //PUT事件,目录下有了新key 88 service.nodes[string(event.Kv.Key)] = string(event.Kv.Value) 89 case mvccpb.DELETE: //DELETE事件,目录中有key被删掉(Lease过期,key 也会被删掉) 90 delete(service.nodes, string(event.Kv.Key)) 91 } 92 service.mutex.Unlock() 93 } 94 } 95 }() 96 } 97 98 type RoundRipper struct { 99 host string 100 index atomic.Int64 101 ips []string 102 } 103 104 func (r *RoundRipper) GetIP() string { 105 r1 := r.index.Add(1) 106 return r.ips[r1%len(r.ips)] 107 } 108 109 func NewRoundRipper(host string, ips []string) *RoundRipper { 110 return &RoundRipper{index: 0, ips: ips} 111 }