github.com/godaddy-x/freego@v1.0.156/rpcx/consulx.go (about) 1 package rpcx 2 3 import ( 4 "fmt" 5 "github.com/godaddy-x/freego/cache" 6 DIC "github.com/godaddy-x/freego/common" 7 "github.com/godaddy-x/freego/utils" 8 "github.com/godaddy-x/freego/zlog" 9 consulapi "github.com/hashicorp/consul/api" 10 "go.uber.org/zap" 11 "net/http" 12 "time" 13 ) 14 15 var ( 16 consulSessions = make(map[string]*ConsulManager, 0) 17 consulSlowlog *zap.Logger 18 queryOptions = &consulapi.QueryOptions{ 19 UseCache: true, 20 MaxAge: 7200 * time.Second, 21 StaleIfError: 14400 * time.Second, 22 } 23 ) 24 25 const ( 26 DefaultConsulDockerHost = "172.17.0.1:8500" 27 DefaultConsulLocalHost = "127.0.0.1:8500" 28 DefaultConsulDomainHost = "consulx.com:8500" 29 ) 30 31 type ConsulManager struct { 32 Host string 33 Token string 34 Consulx *consulapi.Client 35 Config *ConsulConfig 36 } 37 38 // Consulx配置参数 39 type ConsulConfig struct { 40 DsName string // 数据源名 41 Host string // consul host 42 CheckPort int // 健康监测端口 43 RpcPort int // RPC调用端口 44 Protocol string // RPC协议, tcp 45 Timeout string // 请求超时时间, 3s 46 Interval string // 健康监测时间, 5s 47 DestroyAfter string // 销毁服务时间, 600s 48 CheckPath string // 健康检测path /xxx/check 49 LogPath string // 日志输出路径 50 SlowQuery int64 // 0.不开启筛选 >0开启筛选查询 毫秒 51 SlowLogPath string // 慢查询写入地址 52 } 53 54 func getConsulClient(conf ConsulConfig) *ConsulManager { 55 config := consulapi.DefaultConfig() 56 config.Address = conf.Host 57 client, err := consulapi.NewClient(config) 58 if err != nil { 59 panic(utils.AddStr("consul [", conf.Host, "] init failed: ", err)) 60 } 61 return &ConsulManager{Consulx: client, Host: conf.Host} 62 } 63 64 func (self *ConsulManager) InitConfig(input ...ConsulConfig) (*ConsulManager, error) { 65 for _, conf := range input { 66 if len(conf.Host) == 0 { 67 panic("consul host is nil") 68 } 69 if len(conf.DsName) == 0 { 70 conf.DsName = DIC.MASTER 71 } 72 manager := getConsulClient(conf) 73 manager.Config = &conf 74 consulSessions[manager.Config.DsName] = manager 75 manager.initSlowLog() 76 zlog.Printf("consul service %s【%s】has been started successful", conf.Host, conf.DsName) 77 } 78 if len(consulSessions) == 0 { 79 zlog.Printf("consul init failed: sessions is nil") 80 } 81 return self, nil 82 } 83 84 func InitDefaultConsul() { 85 config := ConsulConfig{Host: DefaultConsulDockerHost} 86 if _, err := new(ConsulManager).InitConfig(config); err != nil { 87 panic(err) 88 } 89 } 90 91 func InitHostConsul(host string) { 92 config := ConsulConfig{Host: host} 93 if _, err := new(ConsulManager).InitConfig(config); err != nil { 94 panic(err) 95 } 96 } 97 98 func NewConsul(ds ...string) (*ConsulManager, error) { 99 return new(ConsulManager).Client(ds...) 100 } 101 102 func (self *ConsulManager) initSlowLog() { 103 if self.Config.SlowQuery == 0 || len(self.Config.SlowLogPath) == 0 { 104 return 105 } 106 if consulSlowlog == nil { 107 consulSlowlog = zlog.InitNewLog(&zlog.ZapConfig{ 108 Level: "warn", 109 Console: false, 110 FileConfig: &zlog.FileConfig{ 111 Compress: true, 112 Filename: self.Config.SlowLogPath, 113 MaxAge: 7, 114 MaxBackups: 7, 115 MaxSize: 512, 116 }}) 117 fmt.Println("consul monitoring service started successful...") 118 } 119 } 120 121 func (self *ConsulManager) GetSlowLog() *zap.Logger { 122 return consulSlowlog 123 } 124 125 func (self *ConsulManager) Client(ds ...string) (*ConsulManager, error) { 126 dsName := DIC.MASTER 127 if len(ds) > 0 && len(ds[0]) > 0 { 128 dsName = ds[0] 129 } 130 manager := consulSessions[dsName] 131 if manager == nil { 132 return nil, utils.Error("consul session [", ds, "] not found...") 133 } 134 return manager, nil 135 } 136 137 // 通过Consul中心获取指定JSON配置数据 138 func (self *ConsulManager) GetJsonValue(key string, result interface{}) error { 139 client := self.Consulx 140 kv := client.KV() 141 if kv == nil { 142 return utils.Error("consul node [", key, "] not found...") 143 } 144 k, _, err := kv.Get(key, nil) 145 if err != nil { 146 return utils.Error("consul node [", key, "] read failed...") 147 } 148 if k == nil || k.Value == nil || len(k.Value) == 0 { 149 return utils.Error("consul node [", key, "] read is nil...") 150 } 151 if err := utils.JsonUnmarshal(k.Value, result); err != nil { 152 return utils.Error("consul node [", key, "] parse failed...") 153 } 154 return nil 155 } 156 157 // 通过Consul中心获取指定加密JSON配置数据 158 func (self *ConsulManager) GetAesJsonValue(key, encKey string, result interface{}) error { 159 client := self.Consulx 160 kv := client.KV() 161 if kv == nil { 162 return utils.Error("consul node [", key, "] not found...") 163 } 164 k, _, err := kv.Get(key, nil) 165 if err != nil { 166 return utils.Error("consul node [", key, "] read failed...") 167 } 168 if k == nil || k.Value == nil || len(k.Value) == 0 { 169 return utils.Error("consul node [", key, "] read is nil...") 170 } 171 bts, err := utils.AesDecrypt(utils.Bytes2Str(k.Value), encKey, encKey) 172 if err != nil { 173 return err 174 } 175 if err := utils.JsonUnmarshal(bts, result); err != nil { 176 return utils.Error("consul node [", key, "] parse failed...") 177 } 178 return nil 179 } 180 181 func (self *ConsulManager) GetTextValue(key string) ([]byte, error) { 182 client := self.Consulx 183 kv := client.KV() 184 if kv == nil { 185 return nil, utils.Error("consul node [", key, "] not found...") 186 } 187 k, _, err := kv.Get(key, nil) 188 if err != nil { 189 return nil, utils.Error("consul node [", key, "] read failed...") 190 } 191 if k == nil || k.Value == nil || len(k.Value) == 0 { 192 return nil, utils.Error("consul node [", key, "] read is nil...") 193 } 194 return k.Value, nil 195 } 196 197 func (self *ConsulManager) RemoveService(serviceIDs ...string) { 198 services, err := self.Consulx.Agent().Services() 199 if err != nil { 200 panic(err) 201 } 202 if len(serviceIDs) > 0 { 203 for _, v := range services { 204 for _, ID := range serviceIDs { 205 if ID == v.ID { 206 if err := self.Consulx.Agent().ServiceDeregister(v.ID); err != nil { 207 zlog.Println(err) 208 } 209 zlog.Println("remove grpc service successful: ", v.Service, " - ", v.ID) 210 } 211 } 212 } 213 return 214 } 215 for _, v := range services { 216 if err := self.Consulx.Agent().ServiceDeregister(v.ID); err != nil { 217 zlog.Println(err) 218 } 219 zlog.Println("remove grpc service successful: ", v.Service, " - ", v.ID) 220 } 221 } 222 223 // 根据服务名获取可用列表 224 func (self *ConsulManager) GetAllService(service string) ([]*consulapi.AgentService, error) { 225 result := make([]*consulapi.AgentService, 0) 226 services, err := self.Consulx.Agent().Services() 227 if err != nil { 228 return result, err 229 } 230 if len(service) == 0 { 231 for _, v := range services { 232 result = append(result, v) 233 } 234 return result, nil 235 } 236 for _, v := range services { 237 if service == v.Service { 238 result = append(result, v) 239 } 240 } 241 return result, nil 242 } 243 244 var localCache = cache.NewLocalCache(30, 5) 245 246 func (self *ConsulManager) GetHealthService(service, tag string) ([]*consulapi.ServiceEntry, error) { 247 serviceEntry, _, err := self.Consulx.Health().Service(service, tag, false, queryOptions) 248 if err != nil { 249 return nil, err 250 } 251 if len(serviceEntry) == 0 { 252 return nil, utils.Error("no available services found: [", service, "]") 253 } 254 return serviceEntry, nil 255 } 256 257 func (self *ConsulManager) GetCacheService(service, tag string, cacheSecond int) ([]*consulapi.ServiceEntry, error) { 258 if cacheSecond <= 0 { 259 return self.GetHealthService(service, tag) 260 } 261 cvl, has, err := localCache.Get("consul.grpc."+service+"."+tag, nil) 262 if err != nil { 263 return nil, err 264 } 265 if has && cvl != nil { 266 return cvl.([]*consulapi.ServiceEntry), nil 267 } 268 serviceEntry, err := self.GetHealthService(service, tag) 269 if err != nil { 270 return nil, err 271 } 272 if err := localCache.Put("consul.grpc."+service+"."+tag, serviceEntry, cacheSecond); err != nil { 273 return nil, err 274 } 275 return serviceEntry, nil 276 } 277 278 func (self *ConsulManager) CheckService(services []*consulapi.AgentService, srvName, addr string) bool { 279 for _, v := range services { 280 if v.Service == srvName && v.Address == addr { 281 return true 282 } 283 } 284 return false 285 } 286 287 // 接口服务健康检查 288 func (self *ConsulManager) HealthCheck(w http.ResponseWriter, r *http.Request) { 289 if _, err := fmt.Fprintln(w, "consulCheck"); err != nil { 290 zlog.Error("consul check output failed", 0, zlog.AddError(err)) 291 } 292 }