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 }