dubbo.apache.org/dubbo-go/v3@v3.1.1/registry/service_instance.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 registry
    19  
    20  import (
    21  	"encoding/json"
    22  	url2 "net/url"
    23  	"strconv"
    24  )
    25  
    26  import (
    27  	"github.com/dubbogo/gost/log/logger"
    28  	gxsort "github.com/dubbogo/gost/sort"
    29  )
    30  
    31  import (
    32  	"dubbo.apache.org/dubbo-go/v3/common"
    33  	"dubbo.apache.org/dubbo-go/v3/common/constant"
    34  )
    35  
    36  // ServiceInstance is the interface  which is used for service registration and discovery.
    37  type ServiceInstance interface {
    38  
    39  	// GetID will return this instance's id. It should be unique.
    40  	GetID() string
    41  
    42  	// GetServiceName will return the serviceName
    43  	GetServiceName() string
    44  
    45  	// GetHost will return the hostname
    46  	GetHost() string
    47  
    48  	// GetPort will return the port.
    49  	GetPort() int
    50  
    51  	// IsEnable will return the enable status of this instance
    52  	IsEnable() bool
    53  
    54  	// IsHealthy will return the value represent the instance whether healthy or not
    55  	IsHealthy() bool
    56  
    57  	// GetMetadata will return the metadata
    58  	GetMetadata() map[string]string
    59  
    60  	// ToURLs will return a list of url
    61  	ToURLs(service *common.ServiceInfo) []*common.URL
    62  
    63  	// GetEndPoints will get end points from metadata
    64  	GetEndPoints() []*Endpoint
    65  
    66  	// Copy will return a instance with different port
    67  	Copy(endpoint *Endpoint) ServiceInstance
    68  
    69  	// GetAddress will return the ip:Port
    70  	GetAddress() string
    71  
    72  	// SetServiceMetadata saves metadata in instance
    73  	SetServiceMetadata(info *common.MetadataInfo)
    74  
    75  	// GetTag will return the tag of the instance
    76  	GetTag() string
    77  }
    78  
    79  // nolint
    80  type Endpoint struct {
    81  	Port     int    `json:"port,omitempty"`
    82  	Protocol string `json:"protocol,omitempty"`
    83  }
    84  
    85  // DefaultServiceInstance the default implementation of ServiceInstance
    86  // or change the ServiceInstance to be struct???
    87  type DefaultServiceInstance struct {
    88  	ID              string
    89  	ServiceName     string
    90  	Host            string
    91  	Port            int
    92  	Enable          bool
    93  	Healthy         bool
    94  	Metadata        map[string]string
    95  	ServiceMetadata *common.MetadataInfo
    96  	Address         string
    97  	GroupName       string
    98  	endpoints       []*Endpoint `json:"-"`
    99  	Tag             string
   100  }
   101  
   102  // GetID will return this instance's id. It should be unique.
   103  func (d *DefaultServiceInstance) GetID() string {
   104  	return d.ID
   105  }
   106  
   107  // GetServiceName will return the serviceName
   108  func (d *DefaultServiceInstance) GetServiceName() string {
   109  	return d.ServiceName
   110  }
   111  
   112  // GetHost will return the hostname
   113  func (d *DefaultServiceInstance) GetHost() string {
   114  	return d.Host
   115  }
   116  
   117  // GetPort will return the port.
   118  func (d *DefaultServiceInstance) GetPort() int {
   119  	return d.Port
   120  }
   121  
   122  // IsEnable will return the enable status of this instance
   123  func (d *DefaultServiceInstance) IsEnable() bool {
   124  	return d.Enable
   125  }
   126  
   127  // IsHealthy will return the value represent the instance whether healthy or not
   128  func (d *DefaultServiceInstance) IsHealthy() bool {
   129  	return d.Healthy
   130  }
   131  
   132  // GetAddress will return the ip:Port
   133  func (d *DefaultServiceInstance) GetAddress() string {
   134  	if d.Address != "" {
   135  		return d.Address
   136  	}
   137  	if d.Port <= 0 {
   138  		d.Address = d.Host
   139  	} else {
   140  		d.Address = d.Host + ":" + strconv.Itoa(d.Port)
   141  	}
   142  	return d.Address
   143  }
   144  
   145  // SetServiceMetadata save metadata in instance
   146  func (d *DefaultServiceInstance) SetServiceMetadata(m *common.MetadataInfo) {
   147  	d.ServiceMetadata = m
   148  }
   149  
   150  func (d *DefaultServiceInstance) GetTag() string {
   151  	return d.Tag
   152  }
   153  
   154  // ToURLs return a list of url.
   155  func (d *DefaultServiceInstance) ToURLs(service *common.ServiceInfo) []*common.URL {
   156  	urls := make([]*common.URL, 0, 8)
   157  	if d.endpoints == nil {
   158  		err := json.Unmarshal([]byte(d.Metadata[constant.ServiceInstanceEndpoints]), &d.endpoints)
   159  		if err != nil {
   160  			logger.Errorf("Error parsing endpoints of service instance v%, multiple protocol services might not be able to work properly, err is v%.", d, err)
   161  		}
   162  	}
   163  
   164  	if len(d.endpoints) > 0 {
   165  		for _, endpoint := range d.endpoints {
   166  			if endpoint.Protocol == service.Protocol {
   167  				url := common.NewURLWithOptions(common.WithProtocol(service.Protocol),
   168  					common.WithIp(d.Host), common.WithPort(strconv.Itoa(endpoint.Port)),
   169  					common.WithPath(service.Name), common.WithInterface(service.Name),
   170  					common.WithMethods(service.GetMethods()), common.WithParams(service.GetParams()),
   171  					common.WithParams(url2.Values{constant.Tagkey: {d.Tag}}))
   172  				urls = append(urls, url)
   173  			}
   174  		}
   175  	} else {
   176  		url := common.NewURLWithOptions(common.WithProtocol(service.Protocol),
   177  			common.WithIp(d.Host), common.WithPort(strconv.Itoa(d.Port)),
   178  			common.WithPath(service.Name), common.WithInterface(service.Name),
   179  			common.WithMethods(service.GetMethods()), common.WithParams(service.GetParams()),
   180  			common.WithParams(url2.Values{constant.Tagkey: {d.Tag}}))
   181  		urls = append(urls, url)
   182  	}
   183  	return urls
   184  }
   185  
   186  // GetEndPoints get end points from metadata
   187  func (d *DefaultServiceInstance) GetEndPoints() []*Endpoint {
   188  	rawEndpoints := d.Metadata[constant.ServiceInstanceEndpoints]
   189  	if len(rawEndpoints) == 0 {
   190  		return nil
   191  	}
   192  	var endpoints []*Endpoint
   193  	err := json.Unmarshal([]byte(rawEndpoints), &endpoints)
   194  	if err != nil {
   195  		logger.Errorf("json umarshal rawEndpoints[%s] catch error:%s", rawEndpoints, err.Error())
   196  		return nil
   197  	}
   198  	return endpoints
   199  }
   200  
   201  // Copy return a instance with different port
   202  func (d *DefaultServiceInstance) Copy(endpoint *Endpoint) ServiceInstance {
   203  	dn := &DefaultServiceInstance{
   204  		ID:              d.ID,
   205  		ServiceName:     d.ServiceName,
   206  		Host:            d.Host,
   207  		Port:            endpoint.Port,
   208  		Enable:          d.Enable,
   209  		Healthy:         d.Healthy,
   210  		Metadata:        d.Metadata,
   211  		ServiceMetadata: d.ServiceMetadata,
   212  		Tag:             d.Tag,
   213  	}
   214  	dn.ID = d.GetAddress()
   215  	return dn
   216  }
   217  
   218  // GetMetadata will return the metadata, it will never return nil
   219  func (d *DefaultServiceInstance) GetMetadata() map[string]string {
   220  	if d.Metadata == nil {
   221  		d.Metadata = make(map[string]string)
   222  	}
   223  	return d.Metadata
   224  }
   225  
   226  // ServiceInstanceCustomizer is an extension point which allow user using custom
   227  // logic to modify instance. Be careful of priority. Usually you should use number
   228  // between [100, 9000] other number will be thought as system reserve number
   229  type ServiceInstanceCustomizer interface {
   230  	gxsort.Prioritizer
   231  
   232  	Customize(instance ServiceInstance)
   233  }