package etcd import ( "context" "fmt" "log" "time" "git.apinb.com/bsm-sdk/engine/types" "go.etcd.io/etcd/api/v3/mvccpb" "go.etcd.io/etcd/client/pkg/v3/transport" clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc" ) // Etcd . type Etcd struct { Client *clientv3.Client Kv clientv3.KV Watcher clientv3.Watcher } var ( WithPrefix = clientv3.WithPrefix() IsDelete = mvccpb.DELETE MeshEtcdClient *Etcd = nil PreKv = clientv3.WithPrevKV() ) // NewEtcd . func NewEtcd(endpoints []string, tls *types.EtcdTls) *Etcd { if MeshEtcdClient != nil { return MeshEtcdClient } cfg := clientv3.Config{ Context: context.Background(), Endpoints: endpoints, // set timeout per request to fail fast when the target endpoints is unavailable DialKeepAliveTimeout: 10 * time.Second, DialTimeout: 5 * time.Second, DialOptions: []grpc.DialOption{ grpc.WithBlock(), }, } // 证书 if tls != nil { tlsInfo := transport.TLSInfo{ TrustedCAFile: tls.Ca, CertFile: tls.Cert, KeyFile: tls.CertKey, } _tlsConfig, err := tlsInfo.ClientConfig() if err != nil { log.Fatal(fmt.Sprintf("tlsconfig failed, err: %v", err)) } cfg.TLS = _tlsConfig } client, err := clientv3.New(cfg) if err != nil { log.Fatal(fmt.Sprintf("new etcd client v3 by config %+v error:%s", cfg, err)) } //检测etcd服务是否连接畅通 timeoutCtx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() _, err = client.Status(timeoutCtx, cfg.Endpoints[0]) if err != nil { log.Fatal(fmt.Sprintf("error checking etcd status: %v", err)) } MeshEtcdClient = &Etcd{ Client: client, Kv: clientv3.NewKV(client), Watcher: clientv3.NewWatcher(client), } return MeshEtcdClient } func (e *Etcd) Get(key string) (string, int64, error) { var err error var val string var version int64 resp, err := e.Kv.Get(context.Background(), key) if err == nil && len(resp.Kvs) != 0 { val = string(resp.Kvs[0].Value) version = resp.Kvs[0].ModRevision } return val, version, err } func (e *Etcd) Fetch(key string) ([]*mvccpb.KeyValue, error) { var err error resp, err := e.Kv.Get(context.Background(), key, clientv3.WithPrefix()) return resp.Kvs, err } func (e *Etcd) GetWithRev(key string, version int64) (string, error) { var err error var val string resp, err := e.Kv.Get(context.Background(), key, clientv3.WithRev(version)) if err == nil && len(resp.Kvs) != 0 { val = string(resp.Kvs[0].Value) } return val, err }