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  }