gitee.com/h79/goutils@v1.22.10/discovery/zookeeper/service.go (about) 1 package zookeeper 2 3 import ( 4 "encoding/json" 5 "fmt" 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 "github.com/go-zookeeper/zk" 12 "sync" 13 "time" 14 ) 15 16 var _ service.Service = (*zkService)(nil) 17 18 type zkService struct { 19 Base 20 id string 21 conf config.Config 22 locker sync.Mutex 23 stop chan bool 24 } 25 26 // NewService 27 // 注册一个服务 28 func NewService(cfg config.Config, points config.EndPoints, registry registry.Registry) (service.Service, error) { 29 30 cli, err := NewClientZk(&points, cfg.Node, 30) 31 if err != nil { 32 return nil, err 33 } 34 logger.Info("Zookeeper.service: create client") 35 36 s, err := NewServiceWith(cli, cfg) 37 if err != nil { 38 cli.Close() 39 } 40 return s, err 41 } 42 43 func NewServiceWith(cli *zk.Conn, cfg config.Config) (service.Service, error) { 44 45 id := fmt.Sprintf("service: %s", cfg.Server.To()) 46 47 path := cfg.Node.NameWith("") 48 49 exists, _, err := cli.Exists(path) 50 if err != nil { 51 return nil, err 52 } 53 54 if !exists { //不存在,注册一个服务 55 _, err := cli.Create(path, []byte(""), 0, zk.WorldACL(zk.PermAll)) 56 if err != nil && err != zk.ErrNodeExists { 57 58 return nil, err 59 } 60 } 61 62 data, err := json.Marshal(&cfg.Server) 63 if err != nil { 64 return nil, err 65 } 66 67 path += "/n" 68 _, err = cli.CreateProtectedEphemeralSequential(path, data, zk.WorldACL(zk.PermAll)) 69 if err != nil { 70 return nil, err 71 } 72 73 ser := &zkService{Base: Base{ 74 conn: cli, 75 }, id: id, conf: cfg, stop: make(chan bool)} 76 77 return ser, nil 78 } 79 80 // Start 81 /** 82 * Service interface 83 * 使用 goroutine go Start 84 */ 85 func (s *zkService) Start() error { 86 system.ChildRunning(s.keepAlive) 87 system.ChildRunning(s.close) 88 return nil 89 } 90 91 // Stop interface 92 func (s *zkService) Stop() { 93 system.Stop(time.Second, s.stop) 94 } 95 96 func (s *zkService) close() { 97 for { 98 select { 99 case <-s.stop: 100 s.revoke() 101 s.stop <- true 102 return 103 104 case <-system.Closed(): 105 logger.Error("Zookeeper.service: close because system close") 106 s.revoke() 107 return 108 } 109 } 110 } 111 112 func (s *zkService) keepAlive() { 113 if !s.conf.Check.Ttl { 114 return 115 } 116 ticker := time.NewTicker(time.Second * 8) 117 for { 118 select { 119 case err := <-s.stop: 120 logger.Error("Zookeeper.service: keepAlive stop, err= %v", err) 121 return 122 123 case <-ticker.C: 124 var path = s.conf.Node.NameWith("") 125 if _, err := s.conn.CreateTTL(path, nil, zk.FlagTTL, zk.WorldACL(zk.PermAll), 10000); err != nil { 126 logger.Error("Zookeeper.service: update ttl err= %v", err) 127 } 128 129 case <-system.Closed(): 130 return 131 } 132 } 133 } 134 135 func (s *zkService) revoke() { 136 s.conn.Close() 137 }