gitee.com/h79/goutils@v1.22.10/discovery/consul/service.go (about) 1 /** 2 * by huqiuyun 3 * 启动一个服务时,注册到consul中心,从而可以收到配置信息的变化通知 4 */ 5 package consul 6 7 import ( 8 "fmt" 9 "gitee.com/h79/goutils/common/logger" 10 "gitee.com/h79/goutils/common/result" 11 "gitee.com/h79/goutils/common/server" 12 "gitee.com/h79/goutils/common/system" 13 "gitee.com/h79/goutils/discovery/config" 14 "gitee.com/h79/goutils/discovery/registry" 15 "gitee.com/h79/goutils/discovery/service" 16 consul "github.com/hashicorp/consul/api" 17 "time" 18 ) 19 20 var _ service.Service = (*clService)(nil) 21 22 type clService struct { 23 Base 24 id string 25 serviceName string 26 conf config.Config 27 stop chan bool 28 } 29 30 func NewService(cfg config.Config, points config.EndPoints, registry registry.Registry) (service.Service, error) { 31 32 // initial consul client config 33 cli, err := NewClientWithPoints(points) 34 if err != nil { 35 return nil, err 36 } 37 logger.Info("Consul.service: create consul client") 38 id := fmt.Sprintf("service: %s", cfg.Server.To()) 39 serviceName := cfg.Node.NameWith("") 40 41 reg := &consul.AgentServiceRegistration{ 42 ID: id, 43 Name: serviceName, 44 Tags: cfg.Tags, 45 Port: cfg.Server.Port, 46 Address: cfg.Server.Host, 47 } 48 logger.Info("Consul.service: register info= %+v", reg) 49 if err = cli.Agent().ServiceRegister(reg); err != nil { 50 return nil, result.Error(result.ErrServiceInternal, 51 fmt.Sprintf("CONSUL.SERVICE: register service= %v", err)) 52 } 53 54 err = registerHealth(cfg.Check, id, serviceName, cli) 55 if err != nil { 56 return nil, result.Error(result.ErrServiceInternal, 57 fmt.Sprintf("[CONSUL.SERVICE] register service check : %v", err)) 58 } 59 60 ser := &clService{ 61 Base: Base{ 62 client: cli, 63 watcher: nil, 64 }, 65 id: id, 66 serviceName: serviceName, 67 conf: cfg, 68 stop: make(chan bool)} 69 70 return ser, nil 71 } 72 73 func registerHealth(conf server.Health, id string, name string, client *consul.Client) error { 74 // initial register service check 75 asc := consul.AgentServiceCheck{Status: consul.HealthPassing} 76 77 duration := fmt.Sprintf("%ds", conf.Interval) 78 79 if conf.Ttl { 80 asc.TTL = duration 81 } else { 82 asc.Interval = duration 83 switch conf.Protocol { 84 case server.KGRpcProtocol: 85 asc.GRPC = conf.URL.To() 86 case server.KHttpProtocol: 87 asc.HTTP = conf.URL.To() 88 case server.KTCPProtocol: 89 asc.TCP = conf.URL.To() 90 } 91 } 92 check := &consul.AgentCheckRegistration{ 93 ID: id, 94 ServiceID: id, 95 Name: name, 96 AgentServiceCheck: asc, 97 } 98 return client.Agent().CheckRegister(check) 99 } 100 101 // Start 102 /** 103 * Service interface 104 * 使用 goroutine go Start 105 */ 106 func (s *clService) Start() error { 107 system.ChildRunning(s.keepAlive) 108 return nil 109 } 110 111 // Stop Service interface 112 func (s *clService) Stop() { 113 system.Stop(time.Second, s.stop) 114 } 115 116 func (s *clService) keepAlive() { 117 ticker := time.NewTicker(time.Second * s.conf.Check.Interval) 118 defer ticker.Stop() 119 for { 120 select { 121 case <-s.stop: 122 s.revoke() 123 s.stop <- true 124 return 125 126 case <-ticker.C: 127 if err := s.client.Agent().UpdateTTL(s.id, "", consul.HealthPassing); err != nil { 128 logger.Error("Consul.service: update ttl err= %v", err) 129 } 130 131 case <-system.Closed(): 132 logger.Error("Consul.service: server stop because system closed") 133 s.revoke() 134 return 135 } 136 } 137 } 138 139 func (s *clService) revoke() { 140 141 err := s.client.Agent().ServiceDeregister(s.id) 142 if err != nil { 143 logger.Error("Consul.service: deregister service err= %v", err) 144 } 145 146 err = s.client.Agent().CheckDeregister(s.id) 147 if err != nil { 148 logger.Error("Consul.service: deregister check err= %v", err) 149 } 150 logger.Info("Consul.service: deregister") 151 }