github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/extend/etcd/etcd.go (about) 1 package etcd 2 3 import ( 4 "context" 5 "github.com/golang/glog" 6 "github.com/isyscore/isc-gobase/bean" 7 "github.com/isyscore/isc-gobase/config" 8 "github.com/isyscore/isc-gobase/constants" 9 "github.com/isyscore/isc-gobase/goid" 10 "github.com/isyscore/isc-gobase/isc" 11 "github.com/isyscore/isc-gobase/logger" 12 //"github.com/isyscore/isc-gobase/tracing" 13 etcdClientV3 "go.etcd.io/etcd/client/v3" 14 "go.uber.org/zap" 15 "google.golang.org/grpc" 16 "io" 17 "time" 18 ) 19 20 var EtcdHooks []GobaseEtcdHook 21 22 func init() { 23 config.LoadConfig() 24 25 if config.ExistConfigFile() && config.GetValueBoolDefault("base.etcd.enable", false) { 26 err := config.GetValueObject("base.etcd", &config.EtcdCfg) 27 if err != nil { 28 logger.Warn("读取etcd配置异常") 29 return 30 } 31 } 32 33 EtcdHooks = []GobaseEtcdHook{} 34 //grpclog.SetLoggerV2(&EtcdLogger{}) 35 } 36 37 func NewEtcdClient() (*EtcdClientWrap, error) { 38 if !config.GetValueBoolDefault("base.etcd.enable", false) { 39 logger.Error("etcd没有配置,请先配置") 40 return nil, nil 41 } 42 43 // 客户端配置 44 etcdCfg := etcdClientV3.Config{ 45 Endpoints: config.EtcdCfg.Endpoints, 46 Username: config.EtcdCfg.Username, 47 Password: config.EtcdCfg.Password, 48 MaxCallSendMsgSize: config.EtcdCfg.MaxCallSendMsgSize, 49 MaxCallRecvMsgSize: config.EtcdCfg.MaxCallRecvMsgSize, 50 RejectOldCluster: config.EtcdCfg.RejectOldCluster, 51 PermitWithoutStream: config.EtcdCfg.PermitWithoutStream, 52 } 53 54 if config.EtcdCfg.AutoSyncInterval != "" { 55 t, err := time.ParseDuration(config.EtcdCfg.AutoSyncInterval) 56 if err != nil { 57 logger.Warn("读取配置【base.etcd.auto-sync-interval】异常", err) 58 } else { 59 etcdCfg.AutoSyncInterval = t 60 } 61 } 62 63 if config.EtcdCfg.DialTimeout != "" { 64 t, err := time.ParseDuration(config.EtcdCfg.DialTimeout) 65 if err != nil { 66 logger.Warn("读取配置【base.etcd.dial-timeout】异常", err) 67 } else { 68 etcdCfg.DialTimeout = t 69 } 70 } 71 72 if config.EtcdCfg.DialKeepAliveTime != "" { 73 t, err := time.ParseDuration(config.EtcdCfg.DialKeepAliveTime) 74 if err != nil { 75 logger.Warn("读取配置【base.etcd.dial-keep-alive-time】异常", err) 76 } else { 77 etcdCfg.DialKeepAliveTime = t 78 } 79 } 80 81 if config.EtcdCfg.DialKeepAliveTimeout != "" { 82 t, err := time.ParseDuration(config.EtcdCfg.DialKeepAliveTimeout) 83 if err != nil { 84 logger.Warn("读取配置【base.etcd.dial-keep-alive-timeout】异常", err) 85 } else { 86 etcdCfg.DialKeepAliveTimeout = t 87 } 88 } 89 90 var etcdClient *etcdClientV3.Client 91 if config.EtcdCfg.DialRetry == "" { 92 _etcdClient, err := etcdClientV3.New(etcdCfg) 93 if err != nil { 94 logger.Error("生成etcd-client失败:%v", err.Error()) 95 return nil, err 96 } 97 etcdClient = _etcdClient 98 } else if config.EtcdCfg.DialRetry == "always" { 99 for { 100 _etcdClient, err := etcdClientV3.New(etcdCfg) 101 if err != nil { 102 logger.Error("尝试连接etcd 失败:%v", err.Error()) 103 continue 104 } 105 etcdClient = _etcdClient 106 break 107 } 108 } else { 109 retryTimes := isc.ToInt(config.EtcdCfg.DialRetry) 110 for i := 0; i < retryTimes; i++ { 111 _etcdClient, err := etcdClientV3.New(etcdCfg) 112 if err != nil { 113 logger.Error("尝试连接etcd 第[%v]次失败:%v", i+1, err.Error()) 114 continue 115 } 116 etcdClient = _etcdClient 117 break 118 } 119 } 120 121 var etcdClientWrap EtcdClientWrap 122 etcdClientWrap = EtcdClientWrap{Client: etcdClient, etcdHooks: EtcdHooks} 123 bean.AddBean(constants.BeanNameEtcdPre, &etcdClientWrap) 124 return &etcdClientWrap, nil 125 } 126 127 func NewEtcdClientWithCfg(etcdCfg etcdClientV3.Config) (*EtcdClientWrap, error) { 128 if !config.GetValueBoolDefault("base.etcd.enable", false) { 129 logger.Error("etcd没有配置,请先配置") 130 return nil, nil 131 } 132 133 etcdClient, err := etcdClientV3.New(etcdCfg) 134 if err != nil { 135 logger.Error("生成etcd-client失败:%v", err.Error()) 136 return nil, err 137 } 138 139 var etcdClientWrap EtcdClientWrap 140 etcdClientWrap = EtcdClientWrap{Client: etcdClient, etcdHooks: EtcdHooks} 141 bean.AddBean(constants.BeanNameEtcdPre, &etcdClientWrap) 142 return &etcdClientWrap, nil 143 } 144 145 func AddEtcdHook(hook GobaseEtcdHook) { 146 EtcdHooks = append(EtcdHooks, hook) 147 client := bean.GetBean(constants.BeanNameEtcdPre) 148 if client == nil { 149 return 150 } 151 etcdClient := client.(*EtcdClientWrap) 152 etcdClient.AddHook(hook) 153 } 154 155 type EtcdClientWrap struct { 156 *etcdClientV3.Client 157 etcdHooks []GobaseEtcdHook 158 } 159 160 type GobaseEtcdHook interface { 161 Before(ctx context.Context, op etcdClientV3.Op) context.Context 162 After(ctx context.Context, op etcdClientV3.Op, pRsp any, err error) 163 } 164 165 func (etcdWrap *EtcdClientWrap) AddHook(etcdHook GobaseEtcdHook) { 166 etcdWrap.etcdHooks = append(etcdWrap.etcdHooks, etcdHook) 167 } 168 169 func (etcdWrap *EtcdClientWrap) Put(ctx context.Context, key, val string, opts ...etcdClientV3.OpOption) (*etcdClientV3.PutResponse, error) { 170 op := etcdClientV3.OpPut(key, val, opts...) 171 for _, hook := range etcdWrap.etcdHooks { 172 ctx = hook.Before(ctx, op) 173 } 174 175 rsp, err := etcdWrap.Client.Put(ctx, key, val, opts...) 176 for _, hook := range etcdWrap.etcdHooks { 177 hook.After(ctx, op, rsp, err) 178 } 179 return rsp, err 180 } 181 182 func (etcdWrap *EtcdClientWrap) Get(ctx context.Context, key string, opts ...etcdClientV3.OpOption) (*etcdClientV3.GetResponse, error) { 183 op := etcdClientV3.OpGet(key, opts...) 184 for _, hook := range etcdWrap.etcdHooks { 185 ctx = hook.Before(ctx, op) 186 } 187 rsp, err := etcdWrap.Client.Get(ctx, key, opts...) 188 for _, hook := range etcdWrap.etcdHooks { 189 hook.After(ctx, op, rsp, err) 190 } 191 return rsp, err 192 } 193 194 func (etcdWrap *EtcdClientWrap) Delete(ctx context.Context, key string, opts ...etcdClientV3.OpOption) (*etcdClientV3.DeleteResponse, error) { 195 op := etcdClientV3.OpDelete(key, opts...) 196 for _, hook := range etcdWrap.etcdHooks { 197 ctx = hook.Before(ctx, op) 198 } 199 200 rsp, err := etcdWrap.Client.Delete(ctx, key, opts...) 201 for _, hook := range etcdWrap.etcdHooks { 202 hook.After(ctx, op, rsp, err) 203 } 204 return rsp, err 205 } 206 207 func (etcdWrap *EtcdClientWrap) Compact(ctx context.Context, rev int64, opts ...etcdClientV3.CompactOption) (*etcdClientV3.CompactResponse, error) { 208 return etcdWrap.Client.Compact(ctx, rev, opts...) 209 } 210 211 func (etcdWrap *EtcdClientWrap) Do(ctx context.Context, op etcdClientV3.Op) (etcdClientV3.OpResponse, error) { 212 for _, hook := range etcdWrap.etcdHooks { 213 ctx = hook.Before(ctx, op) 214 } 215 rsp, err := etcdWrap.Client.Do(ctx, op) 216 for _, hook := range etcdWrap.etcdHooks { 217 goid.Go(func() { 218 hook.After(ctx, op, rsp, err) 219 }) 220 } 221 return rsp, err 222 } 223 224 func (etcdWrap *EtcdClientWrap) Txn(ctx context.Context) etcdClientV3.Txn { 225 return etcdWrap.Client.Txn(ctx) 226 } 227 228 func (etcdWrap *EtcdClientWrap) MemberList(ctx context.Context) (*etcdClientV3.MemberListResponse, error) { 229 return etcdWrap.Client.MemberList(ctx) 230 } 231 232 func (etcdWrap *EtcdClientWrap) MemberAdd(ctx context.Context, peerAddrs []string) (*etcdClientV3.MemberAddResponse, error) { 233 return etcdWrap.Client.MemberAdd(ctx, peerAddrs) 234 } 235 236 func (etcdWrap *EtcdClientWrap) MemberAddAsLearner(ctx context.Context, peerAddrs []string) (*etcdClientV3.MemberAddResponse, error) { 237 return etcdWrap.Client.MemberAddAsLearner(ctx, peerAddrs) 238 } 239 240 func (etcdWrap *EtcdClientWrap) MemberRemove(ctx context.Context, id uint64) (*etcdClientV3.MemberRemoveResponse, error) { 241 return etcdWrap.Client.MemberRemove(ctx, id) 242 } 243 244 func (etcdWrap *EtcdClientWrap) MemberPromote(ctx context.Context, id uint64) (*etcdClientV3.MemberPromoteResponse, error) { 245 return etcdWrap.Client.MemberPromote(ctx, id) 246 } 247 248 func (etcdWrap *EtcdClientWrap) Grant(ctx context.Context, ttl int64) (*etcdClientV3.LeaseGrantResponse, error) { 249 return etcdWrap.Client.Grant(ctx, ttl) 250 } 251 252 func (etcdWrap *EtcdClientWrap) Revoke(ctx context.Context, id etcdClientV3.LeaseID) (*etcdClientV3.LeaseRevokeResponse, error) { 253 return etcdWrap.Client.Revoke(ctx, id) 254 } 255 256 func (etcdWrap *EtcdClientWrap) TimeToLive(ctx context.Context, id etcdClientV3.LeaseID, opts ...etcdClientV3.LeaseOption) (*etcdClientV3.LeaseTimeToLiveResponse, error) { 257 return etcdWrap.Client.TimeToLive(ctx, id, opts...) 258 } 259 260 func (etcdWrap *EtcdClientWrap) Leases(ctx context.Context) (*etcdClientV3.LeaseLeasesResponse, error) { 261 return etcdWrap.Client.Leases(ctx) 262 } 263 264 func (etcdWrap *EtcdClientWrap) KeepAlive(ctx context.Context, id etcdClientV3.LeaseID) (<-chan *etcdClientV3.LeaseKeepAliveResponse, error) { 265 return etcdWrap.Client.KeepAlive(ctx, id) 266 } 267 268 func (etcdWrap *EtcdClientWrap) KeepAliveOnce(ctx context.Context, id etcdClientV3.LeaseID) (*etcdClientV3.LeaseKeepAliveResponse, error) { 269 return etcdWrap.Client.KeepAliveOnce(ctx, id) 270 } 271 272 func (etcdWrap *EtcdClientWrap) Close() error { 273 return etcdWrap.Client.Close() 274 } 275 276 func (etcdWrap *EtcdClientWrap) Watch(ctx context.Context, key string, opts ...etcdClientV3.OpOption) etcdClientV3.WatchChan { 277 return etcdWrap.Client.Watch(ctx, key, opts...) 278 } 279 280 func (etcdWrap *EtcdClientWrap) RequestProgress(ctx context.Context) error { 281 return etcdWrap.Client.RequestProgress(ctx) 282 } 283 284 func (etcdWrap *EtcdClientWrap)Authenticate(ctx context.Context, name string, password string) (*etcdClientV3.AuthenticateResponse, error) { 285 return etcdWrap.Client.Authenticate(ctx, name, password) 286 } 287 288 func (etcdWrap *EtcdClientWrap) AuthEnable(ctx context.Context) (*etcdClientV3.AuthEnableResponse, error) { 289 return etcdWrap.Client.AuthEnable(ctx) 290 } 291 292 func (etcdWrap *EtcdClientWrap) AuthDisable(ctx context.Context) (*etcdClientV3.AuthDisableResponse, error) { 293 return etcdWrap.Client.AuthDisable(ctx) 294 } 295 296 func (etcdWrap *EtcdClientWrap) AuthStatus(ctx context.Context) (*etcdClientV3.AuthStatusResponse, error) { 297 return etcdWrap.Client.AuthStatus(ctx) 298 } 299 300 func (etcdWrap *EtcdClientWrap) UserAdd(ctx context.Context, name string, password string) (*etcdClientV3.AuthUserAddResponse, error) { 301 return etcdWrap.Client.UserAdd(ctx, name, password) 302 } 303 304 func (etcdWrap *EtcdClientWrap) UserAddWithOptions(ctx context.Context, name string, password string, opt *etcdClientV3.UserAddOptions) (*etcdClientV3.AuthUserAddResponse, error) { 305 return etcdWrap.Client.UserAddWithOptions(ctx, name, password, opt) 306 } 307 308 func (etcdWrap *EtcdClientWrap) UserDelete(ctx context.Context, name string) (*etcdClientV3.AuthUserDeleteResponse, error) { 309 return etcdWrap.Client.UserDelete(ctx, name) 310 } 311 312 func (etcdWrap *EtcdClientWrap) UserChangePassword(ctx context.Context, name string, password string) (*etcdClientV3.AuthUserChangePasswordResponse, error) { 313 return etcdWrap.Client.UserChangePassword(ctx, name, password) 314 } 315 316 func (etcdWrap *EtcdClientWrap) UserGrantRole(ctx context.Context, user string, role string) (*etcdClientV3.AuthUserGrantRoleResponse, error) { 317 return etcdWrap.Client.UserGrantRole(ctx, user, role) 318 } 319 320 func (etcdWrap *EtcdClientWrap) UserGet(ctx context.Context, name string) (*etcdClientV3.AuthUserGetResponse, error) { 321 return etcdWrap.Client.UserGet(ctx, name) 322 } 323 324 func (etcdWrap *EtcdClientWrap) UserList(ctx context.Context) (*etcdClientV3.AuthUserListResponse, error) { 325 return etcdWrap.Client.UserList(ctx) 326 } 327 328 func (etcdWrap *EtcdClientWrap) UserRevokeRole(ctx context.Context, name string, role string) (*etcdClientV3.AuthUserRevokeRoleResponse, error) { 329 return etcdWrap.Client.UserRevokeRole(ctx, name, role) 330 } 331 332 func (etcdWrap *EtcdClientWrap) RoleAdd(ctx context.Context, name string) (*etcdClientV3.AuthRoleAddResponse, error) { 333 return etcdWrap.Client.RoleAdd(ctx, name) 334 } 335 336 func (etcdWrap *EtcdClientWrap) RoleGrantPermission(ctx context.Context, name string, key, rangeEnd string, permType etcdClientV3.PermissionType) (*etcdClientV3.AuthRoleGrantPermissionResponse, error) { 337 return etcdWrap.Client.RoleGrantPermission(ctx, name, key, rangeEnd, permType) 338 } 339 340 func (etcdWrap *EtcdClientWrap) RoleGet(ctx context.Context, role string) (*etcdClientV3.AuthRoleGetResponse, error) { 341 return etcdWrap.Client.RoleGet(ctx, role) 342 } 343 344 func (etcdWrap *EtcdClientWrap) RoleList(ctx context.Context) (*etcdClientV3.AuthRoleListResponse, error) { 345 return etcdWrap.Client.RoleList(ctx) 346 } 347 348 func (etcdWrap *EtcdClientWrap) RoleRevokePermission(ctx context.Context, role string, key, rangeEnd string) (*etcdClientV3.AuthRoleRevokePermissionResponse, error) { 349 return etcdWrap.Client.RoleRevokePermission(ctx, role,key, rangeEnd) 350 } 351 352 func (etcdWrap *EtcdClientWrap) RoleDelete(ctx context.Context, role string) (*etcdClientV3.AuthRoleDeleteResponse, error) { 353 return etcdWrap.Client.RoleDelete(ctx, role) 354 } 355 356 func (etcdWrap *EtcdClientWrap) AlarmList(ctx context.Context) (*etcdClientV3.AlarmResponse, error) { 357 return etcdWrap.Client.AlarmList(ctx) 358 } 359 360 func (etcdWrap *EtcdClientWrap) AlarmDisarm(ctx context.Context, m *etcdClientV3.AlarmMember) (*etcdClientV3.AlarmResponse, error) { 361 return etcdWrap.Client.AlarmDisarm(ctx, m) 362 } 363 364 func (etcdWrap *EtcdClientWrap) Defragment(ctx context.Context, endpoint string) (*etcdClientV3.DefragmentResponse, error) { 365 return etcdWrap.Client.Defragment(ctx, endpoint) 366 } 367 368 func (etcdWrap *EtcdClientWrap) Status(ctx context.Context, endpoint string) (*etcdClientV3.StatusResponse, error) { 369 return etcdWrap.Client.Status(ctx, endpoint) 370 } 371 372 func (etcdWrap *EtcdClientWrap) HashKV(ctx context.Context, endpoint string, rev int64) (*etcdClientV3.HashKVResponse, error) { 373 return etcdWrap.Client.HashKV(ctx, endpoint, rev) 374 } 375 376 func (etcdWrap *EtcdClientWrap) Snapshot(ctx context.Context) (io.ReadCloser, error) { 377 return etcdWrap.Client.Snapshot(ctx) 378 } 379 380 func (etcdWrap *EtcdClientWrap) MoveLeader(ctx context.Context, transfereeID uint64) (*etcdClientV3.MoveLeaderResponse, error) { 381 return etcdWrap.Client.MoveLeader(ctx, transfereeID) 382 } 383 384 func (etcdWrap *EtcdClientWrap) WithLogger(lg *zap.Logger) *etcdClientV3.Client { 385 return etcdWrap.Client.WithLogger(lg) 386 } 387 388 func (etcdWrap *EtcdClientWrap) GetLogger() *zap.Logger { 389 return etcdWrap.Client.GetLogger() 390 } 391 392 func (etcdWrap *EtcdClientWrap) Ctx() context.Context { 393 return etcdWrap.Client.Ctx() 394 } 395 396 func (etcdWrap *EtcdClientWrap) Endpoints() []string { 397 return etcdWrap.Client.Endpoints() 398 } 399 400 func (etcdWrap *EtcdClientWrap) SetEndpoints(eps ...string) { 401 etcdWrap.Client.SetEndpoints(eps...) 402 } 403 404 func (etcdWrap *EtcdClientWrap) Sync(ctx context.Context) error { 405 return etcdWrap.Client.Sync(ctx) 406 } 407 408 func (etcdWrap *EtcdClientWrap) Dial(ep string) (*grpc.ClientConn, error) { 409 return etcdWrap.Client.Dial(ep) 410 } 411 412 func (etcdWrap *EtcdClientWrap) ActiveConnection() *grpc.ClientConn { 413 return etcdWrap.Client.ActiveConnection() 414 } 415 416 type EtcdLogger struct{} 417 418 func (g *EtcdLogger) Info(args ...interface{}) { 419 logger.Info("", args...) 420 } 421 422 func (g *EtcdLogger) Infoln(args ...interface{}) { 423 logger.Info("", args...) 424 } 425 426 func (g *EtcdLogger) Infof(format string, args ...interface{}) { 427 logger.Info(format, args) 428 } 429 430 func (g *EtcdLogger) InfoDepth(depth int, args ...interface{}) { 431 logger.Info("", args...) 432 } 433 434 func (g *EtcdLogger) Warning(args ...interface{}) { 435 logger.Warn("", args...) 436 } 437 438 func (g *EtcdLogger) Warningln(args ...interface{}) { 439 logger.Warn("", args...) 440 } 441 442 func (g *EtcdLogger) Warningf(format string, args ...interface{}) { 443 logger.Warn(format, args...) 444 } 445 446 func (g *EtcdLogger) WarningDepth(depth int, args ...interface{}) { 447 logger.Warn("", args...) 448 } 449 450 func (g *EtcdLogger) Error(args ...interface{}) { 451 logger.Error("", args...) 452 } 453 454 func (g *EtcdLogger) Errorln(args ...interface{}) { 455 logger.Error("", args...) 456 } 457 458 func (g *EtcdLogger) Errorf(format string, args ...interface{}) { 459 logger.Error(format, args...) 460 } 461 462 func (g *EtcdLogger) ErrorDepth(depth int, args ...interface{}) { 463 logger.Error("", args...) 464 } 465 466 func (g *EtcdLogger) Fatal(args ...interface{}) { 467 logger.Fatal("", args...) 468 } 469 470 func (g *EtcdLogger) Fatalln(args ...interface{}) { 471 logger.Fatal("", args...) 472 } 473 474 func (g *EtcdLogger) Fatalf(format string, args ...interface{}) { 475 logger.Fatal(format, args...) 476 } 477 478 func (g *EtcdLogger) FatalDepth(depth int, args ...interface{}) { 479 logger.Fatal("", args...) 480 } 481 482 func (g *EtcdLogger) V(l int) bool { 483 return bool(glog.V(glog.Level(l))) 484 } 485 486 //func EtcdTracingIsOpen() bool { 487 // return config.GetValueBoolDefault("base.tracing.enable", false) && config.GetValueBoolDefault("base.tracing.etcd.enable", false) 488 //}