dubbo.apache.org/dubbo-go/v3@v3.1.1/metadata/report/etcd/report.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package etcd 19 20 import ( 21 "encoding/json" 22 "strings" 23 ) 24 25 import ( 26 gxset "github.com/dubbogo/gost/container/set" 27 gxetcd "github.com/dubbogo/gost/database/kv/etcd/v3" 28 "github.com/dubbogo/gost/log/logger" 29 30 perrors "github.com/pkg/errors" 31 ) 32 33 import ( 34 "dubbo.apache.org/dubbo-go/v3/common" 35 "dubbo.apache.org/dubbo-go/v3/common/constant" 36 "dubbo.apache.org/dubbo-go/v3/common/extension" 37 "dubbo.apache.org/dubbo-go/v3/metadata/identifier" 38 "dubbo.apache.org/dubbo-go/v3/metadata/report" 39 "dubbo.apache.org/dubbo-go/v3/metadata/report/factory" 40 "dubbo.apache.org/dubbo-go/v3/registry" 41 ) 42 43 const DEFAULT_ROOT = "dubbo" 44 45 func init() { 46 extension.SetMetadataReportFactory(constant.EtcdV3Key, func() factory.MetadataReportFactory { 47 return &etcdMetadataReportFactory{} 48 }) 49 } 50 51 // etcdMetadataReport is the implementation of MetadataReport based etcd 52 type etcdMetadataReport struct { 53 client *gxetcd.Client 54 root string 55 } 56 57 func (e *etcdMetadataReport) GetConfigKeysByGroup(group string) (*gxset.HashSet, error) { 58 //TODO implement me 59 panic("implement me") 60 } 61 62 // GetAppMetadata get metadata info from etcd 63 func (e *etcdMetadataReport) GetAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier) (*common.MetadataInfo, error) { 64 key := e.getNodeKey(metadataIdentifier) 65 data, err := e.client.Get(key) 66 if err != nil { 67 return nil, err 68 } 69 70 info := &common.MetadataInfo{} 71 return info, json.Unmarshal([]byte(data), info) 72 } 73 74 // PublishAppMetadata publish metadata info to etcd 75 func (e *etcdMetadataReport) PublishAppMetadata(metadataIdentifier *identifier.SubscriberMetadataIdentifier, info *common.MetadataInfo) error { 76 key := e.getNodeKey(metadataIdentifier) 77 value, err := json.Marshal(info) 78 if err == nil { 79 err = e.client.Put(key, string(value)) 80 } 81 82 return err 83 } 84 85 // StoreProviderMetadata will store the metadata 86 // metadata including the basic info of the server, provider info, and other user custom info 87 func (e *etcdMetadataReport) StoreProviderMetadata(providerIdentifier *identifier.MetadataIdentifier, serviceDefinitions string) error { 88 key := e.getNodeKey(providerIdentifier) 89 return e.client.Put(key, serviceDefinitions) 90 } 91 92 // StoreConsumerMetadata will store the metadata 93 // metadata including the basic info of the server, consumer info, and other user custom info 94 func (e *etcdMetadataReport) StoreConsumerMetadata(consumerMetadataIdentifier *identifier.MetadataIdentifier, serviceParameterString string) error { 95 key := e.getNodeKey(consumerMetadataIdentifier) 96 return e.client.Put(key, serviceParameterString) 97 } 98 99 // SaveServiceMetadata will store the metadata 100 // metadata including the basic info of the server, service info, and other user custom info 101 func (e *etcdMetadataReport) SaveServiceMetadata(metadataIdentifier *identifier.ServiceMetadataIdentifier, url *common.URL) error { 102 key := e.getNodeKey(metadataIdentifier) 103 return e.client.Put(key, url.String()) 104 } 105 106 // RemoveServiceMetadata will remove the service metadata 107 func (e *etcdMetadataReport) RemoveServiceMetadata(metadataIdentifier *identifier.ServiceMetadataIdentifier) error { 108 return e.client.Delete(e.getNodeKey(metadataIdentifier)) 109 } 110 111 // GetExportedURLs will look up the exported urls. 112 // if not found, an empty list will be returned. 113 func (e *etcdMetadataReport) GetExportedURLs(metadataIdentifier *identifier.ServiceMetadataIdentifier) ([]string, error) { 114 content, err := e.client.Get(e.getNodeKey(metadataIdentifier)) 115 if err != nil { 116 logger.Errorf("etcdMetadataReport GetExportedURLs err:{%v}", err.Error()) 117 return []string{}, err 118 } 119 if content == "" { 120 return []string{}, nil 121 } 122 return []string{content}, nil 123 } 124 125 // SaveSubscribedData will convert the urlList to json array and then store it 126 func (e *etcdMetadataReport) SaveSubscribedData(subscriberMetadataIdentifier *identifier.SubscriberMetadataIdentifier, urls string) error { 127 key := e.getNodeKey(subscriberMetadataIdentifier) 128 return e.client.Put(key, urls) 129 } 130 131 // GetSubscribedURLs will lookup the url 132 // if not found, an empty list will be returned 133 func (e *etcdMetadataReport) GetSubscribedURLs(subscriberMetadataIdentifier *identifier.SubscriberMetadataIdentifier) ([]string, error) { 134 content, err := e.client.Get(e.getNodeKey(subscriberMetadataIdentifier)) 135 if err != nil { 136 logger.Errorf("etcdMetadataReport GetSubscribedURLs err:{%v}", err.Error()) 137 return nil, err 138 } 139 return []string{content}, nil 140 } 141 142 // GetServiceDefinition will lookup the service definition 143 func (e *etcdMetadataReport) GetServiceDefinition(metadataIdentifier *identifier.MetadataIdentifier) (string, error) { 144 key := e.getNodeKey(metadataIdentifier) 145 content, err := e.client.Get(key) 146 if err != nil { 147 logger.Errorf("etcdMetadataReport GetServiceDefinition err:{%v}", err.Error()) 148 return "", err 149 } 150 return content, nil 151 } 152 153 // RegisterServiceAppMapping map the specified Dubbo service interface to current Dubbo app name 154 func (e *etcdMetadataReport) RegisterServiceAppMapping(key string, group string, value string) error { 155 path := e.root + constant.PathSeparator + group + constant.PathSeparator + key 156 oldVal, err := e.client.Get(path) 157 if perrors.Cause(err) == gxetcd.ErrKVPairNotFound { 158 return e.client.Put(path, value) 159 } else if err != nil { 160 return err 161 } 162 if strings.Contains(oldVal, value) { 163 return nil 164 } 165 value = oldVal + constant.CommaSeparator + value 166 return e.client.Put(path, value) 167 } 168 169 // GetServiceAppMapping get the app names from the specified Dubbo service interface 170 func (e *etcdMetadataReport) GetServiceAppMapping(key string, group string, listener registry.MappingListener) (*gxset.HashSet, error) { 171 path := e.root + constant.PathSeparator + group + constant.PathSeparator + key 172 v, err := e.client.Get(path) 173 if err != nil { 174 return nil, err 175 } 176 appNames := strings.Split(v, constant.CommaSeparator) 177 set := gxset.NewSet() 178 for _, app := range appNames { 179 set.Add(app) 180 } 181 return set, nil 182 } 183 184 func (e *etcdMetadataReport) RemoveServiceAppMappingListener(key string, group string) error { 185 return nil 186 } 187 188 type etcdMetadataReportFactory struct{} 189 190 // CreateMetadataReport get the MetadataReport instance of etcd 191 func (e *etcdMetadataReportFactory) CreateMetadataReport(url *common.URL) report.MetadataReport { 192 timeout := url.GetParamDuration(constant.TimeoutKey, constant.DefaultRegTimeout) 193 addresses := strings.Split(url.Location, ",") 194 client, err := gxetcd.NewClient(gxetcd.MetadataETCDV3Client, addresses, timeout, 1) 195 if err != nil { 196 logger.Errorf("Could not create etcd metadata report. URL: %s,error:{%v}", url.String(), err) 197 return nil 198 } 199 group := url.GetParam(constant.GroupKey, DEFAULT_ROOT) 200 group = constant.PathSeparator + strings.TrimPrefix(group, constant.PathSeparator) 201 return &etcdMetadataReport{client: client, root: group} 202 } 203 204 func (e *etcdMetadataReport) getNodeKey(MetadataIdentifier identifier.IMetadataIdentifier) string { 205 var rootDir string 206 if e.root == constant.PathSeparator { 207 rootDir = e.root 208 } else { 209 rootDir = e.root + constant.PathSeparator 210 } 211 return rootDir + MetadataIdentifier.GetFilePathKey() 212 }