dubbo.apache.org/dubbo-go/v3@v3.1.1/xds/balancer/clusterresolver/config.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 /* 19 * 20 * Copyright 2021 gRPC authors. 21 * 22 */ 23 24 package clusterresolver 25 26 import ( 27 "bytes" 28 "encoding/json" 29 "fmt" 30 "strings" 31 ) 32 33 import ( 34 "google.golang.org/grpc/balancer/roundrobin" 35 36 "google.golang.org/grpc/serviceconfig" 37 ) 38 39 import ( 40 "dubbo.apache.org/dubbo-go/v3/xds/balancer/ringhash" 41 internalserviceconfig "dubbo.apache.org/dubbo-go/v3/xds/utils/serviceconfig" 42 ) 43 44 // DiscoveryMechanismType is the type of discovery mechanism. 45 type DiscoveryMechanismType int 46 47 const ( 48 // DiscoveryMechanismTypeEDS is eds. 49 DiscoveryMechanismTypeEDS DiscoveryMechanismType = iota // `json:"EDS"` 50 // DiscoveryMechanismTypeLogicalDNS is DNS. 51 DiscoveryMechanismTypeLogicalDNS // `json:"LOGICAL_DNS"` 52 ) 53 54 // MarshalJSON marshals a DiscoveryMechanismType to a quoted json string. 55 // 56 // This is necessary to handle enum (as strings) from JSON. 57 // 58 // Note that this needs to be defined on the type not pointer, otherwise the 59 // variables of this type will marshal to int not string. 60 func (t DiscoveryMechanismType) MarshalJSON() ([]byte, error) { 61 buffer := bytes.NewBufferString(`"`) 62 switch t { 63 case DiscoveryMechanismTypeEDS: 64 buffer.WriteString("EDS") 65 case DiscoveryMechanismTypeLogicalDNS: 66 buffer.WriteString("LOGICAL_DNS") 67 } 68 buffer.WriteString(`"`) 69 return buffer.Bytes(), nil 70 } 71 72 // UnmarshalJSON unmarshals a quoted json string to the DiscoveryMechanismType. 73 func (t *DiscoveryMechanismType) UnmarshalJSON(b []byte) error { 74 var s string 75 err := json.Unmarshal(b, &s) 76 if err != nil { 77 return err 78 } 79 switch s { 80 case "EDS": 81 *t = DiscoveryMechanismTypeEDS 82 case "LOGICAL_DNS": 83 *t = DiscoveryMechanismTypeLogicalDNS 84 default: 85 return fmt.Errorf("unable to unmarshal string %q to type DiscoveryMechanismType", s) 86 } 87 return nil 88 } 89 90 // DiscoveryMechanism is the discovery mechanism, can be either EDS or DNS. 91 // 92 // For DNS, the ClientConn target will be used for name resolution. 93 // 94 // For EDS, if EDSServiceName is not empty, it will be used for watching. If 95 // EDSServiceName is empty, Cluster will be used. 96 type DiscoveryMechanism struct { 97 // Cluster is the cluster name. 98 Cluster string `json:"cluster,omitempty"` 99 // LoadReportingServerName is the LRS server to send load reports to. If 100 // not present, load reporting will be disabled. If set to the empty string, 101 // load reporting will be sent to the same server that we obtained CDS data 102 // from. 103 LoadReportingServerName *string `json:"lrsLoadReportingServerName,omitempty"` 104 // MaxConcurrentRequests is the maximum number of outstanding requests can 105 // be made to the upstream cluster. Default is 1024. 106 MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"` 107 // Type is the discovery mechanism type. 108 Type DiscoveryMechanismType `json:"type,omitempty"` 109 // EDSServiceName is the EDS service name, as returned in CDS. May be unset 110 // if not specified in CDS. For type EDS only. 111 // 112 // This is used for EDS watch if set. If unset, Cluster is used for EDS 113 // watch. 114 EDSServiceName string `json:"edsServiceName,omitempty"` 115 // DNSHostname is the DNS name to resolve in "host:port" form. For type 116 // LOGICAL_DNS only. 117 DNSHostname string `json:"dnsHostname,omitempty"` 118 } 119 120 // Equal returns whether the DiscoveryMechanism is the same with the parameter. 121 func (dm DiscoveryMechanism) Equal(b DiscoveryMechanism) bool { 122 switch { 123 case dm.Cluster != b.Cluster: 124 return false 125 case !equalStringP(dm.LoadReportingServerName, b.LoadReportingServerName): 126 return false 127 case !equalUint32P(dm.MaxConcurrentRequests, b.MaxConcurrentRequests): 128 return false 129 case dm.Type != b.Type: 130 return false 131 case dm.EDSServiceName != b.EDSServiceName: 132 return false 133 case dm.DNSHostname != b.DNSHostname: 134 return false 135 } 136 return true 137 } 138 139 func equalStringP(a, b *string) bool { 140 if a == nil && b == nil { 141 return true 142 } 143 if a == nil || b == nil { 144 return false 145 } 146 return *a == *b 147 } 148 149 func equalUint32P(a, b *uint32) bool { 150 if a == nil && b == nil { 151 return true 152 } 153 if a == nil || b == nil { 154 return false 155 } 156 return *a == *b 157 } 158 159 // LBConfig is the config for cluster resolver balancer. 160 type LBConfig struct { 161 serviceconfig.LoadBalancingConfig `json:"-"` 162 // DiscoveryMechanisms is an ordered list of discovery mechanisms. 163 // 164 // Must have at least one element. Results from each discovery mechanism are 165 // concatenated together in successive priorities. 166 DiscoveryMechanisms []DiscoveryMechanism `json:"discoveryMechanisms,omitempty"` 167 168 // XDSLBPolicy specifies the policy for locality picking and endpoint picking. 169 // 170 // Note that it's not normal balancing policy, and it can only be either 171 // ROUND_ROBIN or RING_HASH. 172 // 173 // For ROUND_ROBIN, the policy name will be "ROUND_ROBIN", and the config 174 // will be empty. This sets the locality-picking policy to weighted_target 175 // and the endpoint-picking policy to round_robin. 176 // 177 // For RING_HASH, the policy name will be "RING_HASH", and the config will 178 // be lb config for the ring_hash_experimental LB Policy. ring_hash policy 179 // is responsible for both locality picking and endpoint picking. 180 XDSLBPolicy *internalserviceconfig.BalancerConfig `json:"xdsLbPolicy,omitempty"` 181 } 182 183 const ( 184 rrName = roundrobin.Name 185 rhName = ringhash.Name 186 ) 187 188 func parseConfig(c json.RawMessage) (*LBConfig, error) { 189 var cfg LBConfig 190 if err := json.Unmarshal(c, &cfg); err != nil { 191 return nil, err 192 } 193 if lbp := cfg.XDSLBPolicy; lbp != nil && !strings.EqualFold(lbp.Name, rrName) && !strings.EqualFold(lbp.Name, rhName) { 194 return nil, fmt.Errorf("unsupported child policy with name %q, not one of {%q,%q}", lbp.Name, rrName, rhName) 195 } 196 return &cfg, nil 197 }