gitee.com/h79/goutils@v1.22.10/discovery/etcd/service.go (about) 1 package etcd 2 3 import ( 4 "context" 5 "encoding/json" 6 "gitee.com/h79/goutils/common/logger" 7 "gitee.com/h79/goutils/common/system" 8 "gitee.com/h79/goutils/discovery/config" 9 "gitee.com/h79/goutils/discovery/registry" 10 "gitee.com/h79/goutils/discovery/service" 11 clientV3 "go.etcd.io/etcd/client/v3" 12 "time" 13 ) 14 15 var _ service.Service = (*edService)(nil) 16 17 type edService struct { 18 Base 19 lease clientV3.Lease 20 leaseId clientV3.LeaseID 21 cancelFunc func() 22 keepAliveChan <-chan *clientV3.LeaseKeepAliveResponse 23 cfg config.Config 24 } 25 26 // NewService 27 // 注册一个服务 28 func NewService(cfg config.Config, points config.EndPoints, registry registry.Registry) (service.Service, error) { 29 30 cli, err := NewClient3(&points, 30) 31 if err != nil { 32 return nil, err 33 } 34 35 logger.Info("etcd.service: register service") 36 37 return NewServiceWith(cli, cfg) 38 } 39 40 func NewServiceWith(cli *clientV3.Client, cfg config.Config) (service.Service, error) { 41 42 // 创建租约 43 lease := clientV3.NewLease(cli) 44 45 // 设置租约时间 46 leaseResp, err := lease.Grant(context.TODO(), cfg.Check.Interval.Microseconds()) 47 if err != nil { 48 _ = cli.Close() 49 return nil, err 50 } 51 52 // 设置续租 53 ctx, cancelFunc := context.WithCancel(context.TODO()) 54 keepaliveChan, err := lease.KeepAlive(ctx, leaseResp.ID) 55 56 if err != nil { 57 _ = cli.Close() 58 cancelFunc() 59 return nil, err 60 } 61 62 ser := &edService{ 63 Base: Base{ 64 client: cli, 65 watcher: nil, 66 }, 67 lease: lease, 68 leaseId: leaseResp.ID, 69 cancelFunc: cancelFunc, 70 keepAliveChan: keepaliveChan, 71 cfg: cfg, 72 } 73 74 if err = ser.create(); err != nil { 75 ser.Stop() 76 logger.Error("etcd.service: register service failure,%+v", err) 77 return nil, err 78 } 79 80 return ser, nil 81 } 82 83 // Start 84 /** 85 * Service interface 86 * 使用 goroutine go Start 87 */ 88 func (s *edService) Start() error { 89 90 system.ChildRunning(s.keepAlive) 91 92 return nil 93 } 94 95 // Stop interface 96 func (s *edService) Stop() { 97 s.revoke() 98 s.cancelFunc() 99 } 100 101 func (s *edService) keepAlive() { 102 if !s.cfg.Check.Ttl { 103 return 104 } 105 for { 106 select { 107 case c := <-s.keepAliveChan: 108 if c == nil { 109 logger.Error("etcd.service: 已经关闭续租功能") 110 return 111 } else { 112 logger.NDebug("etcd.service: 续租成功") 113 } 114 case <-system.Closed(): 115 return 116 } 117 } 118 } 119 120 func (s *edService) create() error { 121 key := s.cfg.Node.NameWith("") 122 data, err := json.Marshal(&s.cfg.Server) 123 if err != nil { 124 return err 125 } 126 kv := clientV3.NewKV(s.client) 127 _, err = kv.Put(context.TODO(), key, string(data), clientV3.WithLease(s.leaseId)) 128 return err 129 } 130 131 func (s *edService) revoke() { 132 time.Sleep(2 * time.Second) 133 if s.lease != nil { 134 _, _ = s.lease.Revoke(context.TODO(), s.leaseId) 135 s.lease = nil 136 } 137 if s.client != nil { 138 _ = s.client.Close() 139 s.client = nil 140 } 141 }