gitee.com/h79/goutils@v1.22.10/discovery/resolver/builder/builder.go (about) 1 package builder 2 3 import ( 4 "gitee.com/h79/goutils/common/attributes" 5 "gitee.com/h79/goutils/common/random" 6 "sort" 7 "strings" 8 ) 9 10 // Target 11 // - "dns://some_authority/foo.bar" 12 // Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"} 13 type Target struct { 14 // "grpc", "thrift", "local"... 15 Type string `json:"type"` 16 Scheme string `json:"scheme"` 17 Authority string `json:"authority"` 18 Endpoint string `json:"endpoint"` 19 } 20 21 const KDefBuild = "/" 22 23 func (target *Target) SchemeWith(build string) string { 24 addr := "" 25 if len(build) == 0 { 26 build = KDefBuild 27 } 28 if len(target.Scheme) > 0 { 29 addr = target.Scheme + "://" 30 } 31 if len(target.Authority) > 0 { 32 addr += target.Authority 33 } 34 if len(target.Endpoint) > 0 { 35 if len(addr) > 0 { 36 addr += build 37 } 38 addr += target.Endpoint 39 } 40 return addr 41 } 42 43 func (target *Target) NameWith(build string) string { 44 addr := "" 45 if len(build) == 0 { 46 build = KDefBuild 47 } 48 if len(target.Authority) > 0 { 49 addr += target.Authority 50 } 51 if len(target.Endpoint) > 0 { 52 if len(addr) > 0 { 53 addr += build 54 } 55 addr += target.Endpoint 56 } 57 return addr 58 } 59 60 func TargetWithGrpc(scheme, authority, endpoint string) Target { 61 return TargetWith("grpc", scheme, authority, endpoint) 62 } 63 64 func TargetWithThrift(scheme, authority, endpoint string) Target { 65 return TargetWith("thrift", scheme, authority, endpoint) 66 } 67 68 func TargetWithLocal(scheme, authority, endpoint string) Target { 69 return TargetWith("local", scheme, authority, endpoint) 70 } 71 72 func TargetWith(ty, scheme, authority, endpoint string) Target { 73 return Target{ 74 Type: ty, 75 Scheme: scheme, 76 Authority: authority, 77 Endpoint: endpoint, 78 } 79 } 80 81 // split2 returns the values from strings.SplitN(s, sep, 2). 82 // If sep is not found, it returns ("", "", false) instead. 83 func split2(s, sep string) (string, string, bool) { 84 spl := strings.SplitN(s, sep, 2) 85 if len(spl) < 2 { 86 return "", "", false 87 } 88 return spl[0], spl[1], true 89 } 90 91 // ParseTarget splits target into a resolver.Target struct containing scheme, 92 // authority and endpoint. 93 // 94 // If target is not a valid scheme://authority/endpoint, it returns {Endpoint: 95 // target}. 96 func ParseTarget(target string) (ret Target) { 97 var ok bool 98 ret.Scheme, ret.Endpoint, ok = split2(target, "://") 99 if !ok { 100 return Target{Endpoint: target} 101 } 102 ret.Authority, ret.Endpoint, ok = split2(ret.Endpoint, KDefBuild) 103 if !ok { 104 return Target{Endpoint: target} 105 } 106 return ret 107 } 108 109 // Builder creates a resolver that will be used to watch name resolution updates. 110 type Builder interface { 111 // Build creates a new resolver for the given target. 112 // 113 // gRPC dial calls Build synchronously, and fails if the returned error is 114 // not nil. 115 Build(target Target, cc Connector) (Resolver, error) 116 117 // Scheme returns the scheme supported by this resolver. 118 Scheme() string 119 120 Type() string 121 } 122 123 // Resolver watches for the updates on the specified target. 124 // Updates include address updates and service config updates. 125 type Resolver interface { 126 // ResolveNow will be called by gRPC to try to resolve the target name 127 // again. It's just a hint, resolver can ignore this if it's not necessary. 128 // 129 // It could be called multiple times concurrently. 130 ResolveNow() 131 132 // Close closes the resolver. 133 Close() 134 } 135 136 type Connector interface { 137 // UpdateState updates the state of the ClientConn appropriately. 138 UpdateState(State) 139 140 // ReportError notifies the ClientConn that the Resolver encountered an 141 // error. The ClientConn will notify the load balancer and begin calling 142 // ResolveNow on the Resolver with exponential backoff. 143 ReportError(error) 144 } 145 146 // Address Notice: This type is EXPERIMENTAL and may be changed or removed in a 147 // later release. 148 type Address struct { 149 // Addr is the server address on which a connection will be established. 150 Addr string 151 152 // ServerName is the name of this address. 153 // If non-empty, the ServerName is used as the transport certification authority for 154 // the address, instead of the hostname from the Dial target string. In most cases, 155 // this should not be set. 156 // 157 // If Method is GRPCLB, ServerName should be the name of the remote load 158 // balancer, not the name of the backend. 159 // 160 // WARNING: ServerName must only be populated with trusted values. It 161 // is insecure to populate it with data from untrusted inputs since untrusted 162 // values could be used to bypass the authority checks performed by TLS. 163 ServerName string 164 165 // Attributes contains arbitrary data about this address intended for 166 // consumption by the load balancing policy. 167 Attributes *attributes.Attributes 168 169 // Weight sort max in front 170 Weight int64 171 } 172 173 // State contains the current Resolver state relevant to the ClientConn. 174 type State struct { 175 // Addresses is the latest set of resolved addresses for the target. 176 Addresses Addresses 177 178 // Attributes contains arbitrary data about the resolver intended for 179 // consumption by the load balancing policy. 180 Attributes *attributes.Attributes 181 } 182 183 type Addresses []Address 184 185 func (a Addresses) Len() int { 186 return len(a) 187 } 188 189 func (a Addresses) Swap(i, j int) { 190 a[i], a[j] = a[j], a[i] 191 } 192 193 // Less 权重大的在前面 194 func (a Addresses) Less(i, j int) bool { 195 return a[i].Weight >= a[j].Weight 196 } 197 198 func (a Addresses) ToWeight() { 199 r := random.Random() 200 for index, _ := range a { 201 a[index].Weight = r.Int63n(1000) 202 } 203 sort.Sort(a) 204 }