resolver.go

  1/*
  2 *
  3 * Copyright 2017 gRPC authors.
  4 *
  5 * Licensed under the Apache License, Version 2.0 (the "License");
  6 * you may not use this file except in compliance with the License.
  7 * 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// Package resolver defines APIs for name resolution in gRPC.
 20// All APIs in this package are experimental.
 21package resolver
 22
 23import (
 24	"context"
 25	"errors"
 26	"fmt"
 27	"net"
 28	"net/url"
 29	"strings"
 30
 31	"google.golang.org/grpc/attributes"
 32	"google.golang.org/grpc/credentials"
 33	"google.golang.org/grpc/experimental/stats"
 34	"google.golang.org/grpc/internal"
 35	"google.golang.org/grpc/serviceconfig"
 36)
 37
 38var (
 39	// m is a map from scheme to resolver builder.
 40	m = make(map[string]Builder)
 41	// defaultScheme is the default scheme to use.
 42	defaultScheme = "passthrough"
 43)
 44
 45// TODO(bar) install dns resolver in init(){}.
 46
 47// Register registers the resolver builder to the resolver map. b.Scheme will
 48// be used as the scheme registered with this builder. The registry is case
 49// sensitive, and schemes should not contain any uppercase characters.
 50//
 51// NOTE: this function must only be called during initialization time (i.e. in
 52// an init() function), and is not thread-safe. If multiple Resolvers are
 53// registered with the same name, the one registered last will take effect.
 54func Register(b Builder) {
 55	m[b.Scheme()] = b
 56}
 57
 58// Get returns the resolver builder registered with the given scheme.
 59//
 60// If no builder is register with the scheme, nil will be returned.
 61func Get(scheme string) Builder {
 62	if b, ok := m[scheme]; ok {
 63		return b
 64	}
 65	return nil
 66}
 67
 68// SetDefaultScheme sets the default scheme that will be used. The default
 69// scheme is initially set to "passthrough".
 70//
 71// NOTE: this function must only be called during initialization time (i.e. in
 72// an init() function), and is not thread-safe. The scheme set last overrides
 73// previously set values.
 74func SetDefaultScheme(scheme string) {
 75	defaultScheme = scheme
 76	internal.UserSetDefaultScheme = true
 77}
 78
 79// GetDefaultScheme gets the default scheme that will be used by grpc.Dial.  If
 80// SetDefaultScheme is never called, the default scheme used by grpc.NewClient is "dns" instead.
 81func GetDefaultScheme() string {
 82	return defaultScheme
 83}
 84
 85// Address represents a server the client connects to.
 86//
 87// # Experimental
 88//
 89// Notice: This type is EXPERIMENTAL and may be changed or removed in a
 90// later release.
 91type Address struct {
 92	// Addr is the server address on which a connection will be established.
 93	Addr string
 94
 95	// ServerName is the name of this address.
 96	// If non-empty, the ServerName is used as the transport certification authority for
 97	// the address, instead of the hostname from the Dial target string. In most cases,
 98	// this should not be set.
 99	//
100	// WARNING: ServerName must only be populated with trusted values. It
101	// is insecure to populate it with data from untrusted inputs since untrusted
102	// values could be used to bypass the authority checks performed by TLS.
103	ServerName string
104
105	// Attributes contains arbitrary data about this address intended for
106	// consumption by the SubConn.
107	Attributes *attributes.Attributes
108
109	// BalancerAttributes contains arbitrary data about this address intended
110	// for consumption by the LB policy.  These attributes do not affect SubConn
111	// creation, connection establishment, handshaking, etc.
112	//
113	// Deprecated: when an Address is inside an Endpoint, this field should not
114	// be used, and it will eventually be removed entirely.
115	BalancerAttributes *attributes.Attributes
116
117	// Metadata is the information associated with Addr, which may be used
118	// to make load balancing decision.
119	//
120	// Deprecated: use Attributes instead.
121	Metadata any
122}
123
124// Equal returns whether a and o are identical.  Metadata is compared directly,
125// not with any recursive introspection.
126//
127// This method compares all fields of the address. When used to tell apart
128// addresses during subchannel creation or connection establishment, it might be
129// more appropriate for the caller to implement custom equality logic.
130func (a Address) Equal(o Address) bool {
131	return a.Addr == o.Addr && a.ServerName == o.ServerName &&
132		a.Attributes.Equal(o.Attributes) &&
133		a.BalancerAttributes.Equal(o.BalancerAttributes) &&
134		a.Metadata == o.Metadata
135}
136
137// String returns JSON formatted string representation of the address.
138func (a Address) String() string {
139	var sb strings.Builder
140	sb.WriteString(fmt.Sprintf("{Addr: %q, ", a.Addr))
141	sb.WriteString(fmt.Sprintf("ServerName: %q, ", a.ServerName))
142	if a.Attributes != nil {
143		sb.WriteString(fmt.Sprintf("Attributes: %v, ", a.Attributes.String()))
144	}
145	if a.BalancerAttributes != nil {
146		sb.WriteString(fmt.Sprintf("BalancerAttributes: %v", a.BalancerAttributes.String()))
147	}
148	sb.WriteString("}")
149	return sb.String()
150}
151
152// BuildOptions includes additional information for the builder to create
153// the resolver.
154type BuildOptions struct {
155	// DisableServiceConfig indicates whether a resolver implementation should
156	// fetch service config data.
157	DisableServiceConfig bool
158	// DialCreds is the transport credentials used by the ClientConn for
159	// communicating with the target gRPC service (set via
160	// WithTransportCredentials). In cases where a name resolution service
161	// requires the same credentials, the resolver may use this field. In most
162	// cases though, it is not appropriate, and this field may be ignored.
163	DialCreds credentials.TransportCredentials
164	// CredsBundle is the credentials bundle used by the ClientConn for
165	// communicating with the target gRPC service (set via
166	// WithCredentialsBundle). In cases where a name resolution service
167	// requires the same credentials, the resolver may use this field. In most
168	// cases though, it is not appropriate, and this field may be ignored.
169	CredsBundle credentials.Bundle
170	// Dialer is the custom dialer used by the ClientConn for dialling the
171	// target gRPC service (set via WithDialer). In cases where a name
172	// resolution service requires the same dialer, the resolver may use this
173	// field. In most cases though, it is not appropriate, and this field may
174	// be ignored.
175	Dialer func(context.Context, string) (net.Conn, error)
176	// Authority is the effective authority of the clientconn for which the
177	// resolver is built.
178	Authority string
179	// MetricsRecorder is the metrics recorder to do recording.
180	MetricsRecorder stats.MetricsRecorder
181}
182
183// An Endpoint is one network endpoint, or server, which may have multiple
184// addresses with which it can be accessed.
185type Endpoint struct {
186	// Addresses contains a list of addresses used to access this endpoint.
187	Addresses []Address
188
189	// Attributes contains arbitrary data about this endpoint intended for
190	// consumption by the LB policy.
191	Attributes *attributes.Attributes
192}
193
194// State contains the current Resolver state relevant to the ClientConn.
195type State struct {
196	// Addresses is the latest set of resolved addresses for the target.
197	//
198	// If a resolver sets Addresses but does not set Endpoints, one Endpoint
199	// will be created for each Address before the State is passed to the LB
200	// policy.  The BalancerAttributes of each entry in Addresses will be set
201	// in Endpoints.Attributes, and be cleared in the Endpoint's Address's
202	// BalancerAttributes.
203	//
204	// Soon, Addresses will be deprecated and replaced fully by Endpoints.
205	Addresses []Address
206
207	// Endpoints is the latest set of resolved endpoints for the target.
208	//
209	// If a resolver produces a State containing Endpoints but not Addresses,
210	// it must take care to ensure the LB policies it selects will support
211	// Endpoints.
212	Endpoints []Endpoint
213
214	// ServiceConfig contains the result from parsing the latest service
215	// config.  If it is nil, it indicates no service config is present or the
216	// resolver does not provide service configs.
217	ServiceConfig *serviceconfig.ParseResult
218
219	// Attributes contains arbitrary data about the resolver intended for
220	// consumption by the load balancing policy.
221	Attributes *attributes.Attributes
222}
223
224// ClientConn contains the callbacks for resolver to notify any updates
225// to the gRPC ClientConn.
226//
227// This interface is to be implemented by gRPC. Users should not need a
228// brand new implementation of this interface. For the situations like
229// testing, the new implementation should embed this interface. This allows
230// gRPC to add new methods to this interface.
231type ClientConn interface {
232	// UpdateState updates the state of the ClientConn appropriately.
233	//
234	// If an error is returned, the resolver should try to resolve the
235	// target again. The resolver should use a backoff timer to prevent
236	// overloading the server with requests. If a resolver is certain that
237	// reresolving will not change the result, e.g. because it is
238	// a watch-based resolver, returned errors can be ignored.
239	//
240	// If the resolved State is the same as the last reported one, calling
241	// UpdateState can be omitted.
242	UpdateState(State) error
243	// ReportError notifies the ClientConn that the Resolver encountered an
244	// error. The ClientConn then forwards this error to the load balancing
245	// policy.
246	ReportError(error)
247	// NewAddress is called by resolver to notify ClientConn a new list
248	// of resolved addresses.
249	// The address list should be the complete list of resolved addresses.
250	//
251	// Deprecated: Use UpdateState instead.
252	NewAddress(addresses []Address)
253	// ParseServiceConfig parses the provided service config and returns an
254	// object that provides the parsed config.
255	ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult
256}
257
258// Target represents a target for gRPC, as specified in:
259// https://github.com/grpc/grpc/blob/master/doc/naming.md.
260// It is parsed from the target string that gets passed into Dial or DialContext
261// by the user. And gRPC passes it to the resolver and the balancer.
262//
263// If the target follows the naming spec, and the parsed scheme is registered
264// with gRPC, we will parse the target string according to the spec. If the
265// target does not contain a scheme or if the parsed scheme is not registered
266// (i.e. no corresponding resolver available to resolve the endpoint), we will
267// apply the default scheme, and will attempt to reparse it.
268type Target struct {
269	// URL contains the parsed dial target with an optional default scheme added
270	// to it if the original dial target contained no scheme or contained an
271	// unregistered scheme. Any query params specified in the original dial
272	// target can be accessed from here.
273	URL url.URL
274}
275
276// Endpoint retrieves endpoint without leading "/" from either `URL.Path`
277// or `URL.Opaque`. The latter is used when the former is empty.
278func (t Target) Endpoint() string {
279	endpoint := t.URL.Path
280	if endpoint == "" {
281		endpoint = t.URL.Opaque
282	}
283	// For targets of the form "[scheme]://[authority]/endpoint, the endpoint
284	// value returned from url.Parse() contains a leading "/". Although this is
285	// in accordance with RFC 3986, we do not want to break existing resolver
286	// implementations which expect the endpoint without the leading "/". So, we
287	// end up stripping the leading "/" here. But this will result in an
288	// incorrect parsing for something like "unix:///path/to/socket". Since we
289	// own the "unix" resolver, we can workaround in the unix resolver by using
290	// the `URL` field.
291	return strings.TrimPrefix(endpoint, "/")
292}
293
294// String returns the canonical string representation of Target.
295func (t Target) String() string {
296	return t.URL.Scheme + "://" + t.URL.Host + "/" + t.Endpoint()
297}
298
299// Builder creates a resolver that will be used to watch name resolution updates.
300type Builder interface {
301	// Build creates a new resolver for the given target.
302	//
303	// gRPC dial calls Build synchronously, and fails if the returned error is
304	// not nil.
305	Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error)
306	// Scheme returns the scheme supported by this resolver.  Scheme is defined
307	// at https://github.com/grpc/grpc/blob/master/doc/naming.md.  The returned
308	// string should not contain uppercase characters, as they will not match
309	// the parsed target's scheme as defined in RFC 3986.
310	Scheme() string
311}
312
313// ResolveNowOptions includes additional information for ResolveNow.
314type ResolveNowOptions struct{}
315
316// Resolver watches for the updates on the specified target.
317// Updates include address updates and service config updates.
318type Resolver interface {
319	// ResolveNow will be called by gRPC to try to resolve the target name
320	// again. It's just a hint, resolver can ignore this if it's not necessary.
321	//
322	// It could be called multiple times concurrently.
323	ResolveNow(ResolveNowOptions)
324	// Close closes the resolver.
325	Close()
326}
327
328// AuthorityOverrider is implemented by Builders that wish to override the
329// default authority for the ClientConn.
330// By default, the authority used is target.Endpoint().
331type AuthorityOverrider interface {
332	// OverrideAuthority returns the authority to use for a ClientConn with the
333	// given target. The implementation must generate it without blocking,
334	// typically in line, and must keep it unchanged.
335	OverrideAuthority(Target) string
336}
337
338// ValidateEndpoints validates endpoints from a petiole policy's perspective.
339// Petiole policies should call this before calling into their children. See
340// [gRPC A61](https://github.com/grpc/proposal/blob/master/A61-IPv4-IPv6-dualstack-backends.md)
341// for details.
342func ValidateEndpoints(endpoints []Endpoint) error {
343	if len(endpoints) == 0 {
344		return errors.New("endpoints list is empty")
345	}
346
347	for _, endpoint := range endpoints {
348		for range endpoint.Addresses {
349			return nil
350		}
351	}
352	return errors.New("endpoints list contains no addresses")
353}