gitee.com/zhaochuninhefei/gmgo@v0.0.31-0.20240209061119-069254a02979/grpc/resolver/resolver.go (about)

     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.
    21  package resolver
    22  
    23  import (
    24  	"context"
    25  	"net"
    26  	"net/url"
    27  	"strings"
    28  
    29  	"gitee.com/zhaochuninhefei/gmgo/grpc/attributes"
    30  	"gitee.com/zhaochuninhefei/gmgo/grpc/credentials"
    31  	"gitee.com/zhaochuninhefei/gmgo/grpc/serviceconfig"
    32  )
    33  
    34  var (
    35  	// m is a map from scheme to resolver builder.
    36  	m = make(map[string]Builder)
    37  	// defaultScheme is the default scheme to use.
    38  	defaultScheme = "passthrough"
    39  )
    40  
    41  // TODO(bar) install dns resolver in init(){}.
    42  
    43  // Register registers the resolver builder to the resolver map. b.Scheme will be
    44  // used as the scheme registered with this builder.
    45  //
    46  // NOTE: this function must only be called during initialization time (i.e. in
    47  // an init() function), and is not thread-safe. If multiple Resolvers are
    48  // registered with the same name, the one registered last will take effect.
    49  func Register(b Builder) {
    50  	m[b.Scheme()] = b
    51  }
    52  
    53  // Get returns the resolver builder registered with the given scheme.
    54  //
    55  // If no builder is register with the scheme, nil will be returned.
    56  func Get(scheme string) Builder {
    57  	if b, ok := m[scheme]; ok {
    58  		return b
    59  	}
    60  	return nil
    61  }
    62  
    63  // SetDefaultScheme sets the default scheme that will be used. The default
    64  // default scheme is "passthrough".
    65  //
    66  // NOTE: this function must only be called during initialization time (i.e. in
    67  // an init() function), and is not thread-safe. The scheme set last overrides
    68  // previously set values.
    69  func SetDefaultScheme(scheme string) {
    70  	defaultScheme = scheme
    71  }
    72  
    73  // GetDefaultScheme gets the default scheme that will be used.
    74  func GetDefaultScheme() string {
    75  	return defaultScheme
    76  }
    77  
    78  // AddressType indicates the address type returned by name resolution.
    79  //
    80  // ToDeprecated: use Attributes in Address instead.
    81  type AddressType uint8
    82  
    83  const (
    84  	// Backend indicates the address is for a backend server.
    85  	//
    86  	// ToDeprecated: use Attributes in Address instead.
    87  	Backend AddressType = iota
    88  	// GRPCLB indicates the address is for a grpclb load balancer.
    89  	//
    90  	// ToDeprecated: to select the GRPCLB load balancing policy, use a service
    91  	// config with a corresponding loadBalancingConfig.  To supply balancer
    92  	// addresses to the GRPCLB load balancing policy, set State.Attributes
    93  	// using balancer/grpclb/state.Set.
    94  	GRPCLB
    95  )
    96  
    97  // Address represents a server the client connects to.
    98  //
    99  // Experimental
   100  //
   101  // Notice: This type is EXPERIMENTAL and may be changed or removed in a
   102  // later release.
   103  type Address struct {
   104  	// Addr is the server address on which a connection will be established.
   105  	Addr string
   106  
   107  	// ServerName is the name of this address.
   108  	// If non-empty, the ServerName is used as the transport certification authority for
   109  	// the address, instead of the hostname from the Dial target string. In most cases,
   110  	// this should not be set.
   111  	//
   112  	// If Type is GRPCLB, ServerName should be the name of the remote load
   113  	// balancer, not the name of the backend.
   114  	//
   115  	// WARNING: ServerName must only be populated with trusted values. It
   116  	// is insecure to populate it with data from untrusted inputs since untrusted
   117  	// values could be used to bypass the authority checks performed by TLS.
   118  	ServerName string
   119  
   120  	// Attributes contains arbitrary data about this address intended for
   121  	// consumption by the SubConn.
   122  	Attributes *attributes.Attributes
   123  
   124  	// BalancerAttributes contains arbitrary data about this address intended
   125  	// for consumption by the LB policy.  These attribes do not affect SubConn
   126  	// creation, connection establishment, handshaking, etc.
   127  	BalancerAttributes *attributes.Attributes
   128  
   129  	// Type is the type of this address.
   130  	//
   131  	// ToDeprecated: use Attributes instead.
   132  	Type AddressType
   133  
   134  	// Metadata is the information associated with Addr, which may be used
   135  	// to make load balancing decision.
   136  	//
   137  	// ToDeprecated: use Attributes instead.
   138  	Metadata interface{}
   139  }
   140  
   141  // Equal returns whether a and o are identical.  Metadata is compared directly,
   142  // not with any recursive introspection.
   143  func (a *Address) Equal(o Address) bool {
   144  	return a.Addr == o.Addr && a.ServerName == o.ServerName &&
   145  		a.Attributes.Equal(o.Attributes) &&
   146  		a.BalancerAttributes.Equal(o.BalancerAttributes) &&
   147  		a.Type == o.Type && a.Metadata == o.Metadata
   148  }
   149  
   150  // BuildOptions includes additional information for the builder to create
   151  // the resolver.
   152  type BuildOptions struct {
   153  	// DisableServiceConfig indicates whether a resolver implementation should
   154  	// fetch service config data.
   155  	DisableServiceConfig bool
   156  	// DialCreds is the transport credentials used by the ClientConn for
   157  	// communicating with the target gRPC service (set via
   158  	// WithTransportCredentials). In cases where a name resolution service
   159  	// requires the same credentials, the resolver may use this field. In most
   160  	// cases though, it is not appropriate, and this field may be ignored.
   161  	DialCreds credentials.TransportCredentials
   162  	// CredsBundle is the credentials bundle used by the ClientConn for
   163  	// communicating with the target gRPC service (set via
   164  	// WithCredentialsBundle). In cases where a name resolution service
   165  	// requires the same credentials, the resolver may use this field. In most
   166  	// cases though, it is not appropriate, and this field may be ignored.
   167  	CredsBundle credentials.Bundle
   168  	// Dialer is the custom dialer used by the ClientConn for dialling the
   169  	// target gRPC service (set via WithDialer). In cases where a name
   170  	// resolution service requires the same dialer, the resolver may use this
   171  	// field. In most cases though, it is not appropriate, and this field may
   172  	// be ignored.
   173  	Dialer func(context.Context, string) (net.Conn, error)
   174  }
   175  
   176  // State contains the current Resolver state relevant to the ClientConn.
   177  type State struct {
   178  	// Addresses is the latest set of resolved addresses for the target.
   179  	Addresses []Address
   180  
   181  	// ServiceConfig contains the result from parsing the latest service
   182  	// config.  If it is nil, it indicates no service config is present or the
   183  	// resolver does not provide service configs.
   184  	ServiceConfig *serviceconfig.ParseResult
   185  
   186  	// Attributes contains arbitrary data about the resolver intended for
   187  	// consumption by the load balancing policy.
   188  	Attributes *attributes.Attributes
   189  }
   190  
   191  // ClientConn contains the callbacks for resolver to notify any updates
   192  // to the gRPC ClientConn.
   193  //
   194  // This interface is to be implemented by gRPC. Users should not need a
   195  // brand new implementation of this interface. For the situations like
   196  // testing, the new implementation should embed this interface. This allows
   197  // gRPC to add new methods to this interface.
   198  type ClientConn interface {
   199  	// UpdateState updates the state of the ClientConn appropriately.
   200  	UpdateState(State) error
   201  	// ReportError notifies the ClientConn that the Resolver encountered an
   202  	// error.  The ClientConn will notify the load balancer and begin calling
   203  	// ResolveNow on the Resolver with exponential backoff.
   204  	ReportError(error)
   205  	// NewAddress is called by resolver to notify ClientConn a new list
   206  	// of resolved addresses.
   207  	// The address list should be the complete list of resolved addresses.
   208  	//
   209  	// Deprecated: Use UpdateState instead.
   210  	NewAddress(addresses []Address)
   211  	// NewServiceConfig is called by resolver to notify ClientConn a new
   212  	// service config. The service config should be provided as a json string.
   213  	//
   214  	// Deprecated: Use UpdateState instead.
   215  	NewServiceConfig(serviceConfig string)
   216  	// ParseServiceConfig parses the provided service config and returns an
   217  	// object that provides the parsed config.
   218  	ParseServiceConfig(serviceConfigJSON string) *serviceconfig.ParseResult
   219  }
   220  
   221  // Target represents a target for gRPC, as specified in:
   222  // https://github.com/grpc/grpc/blob/master/doc/naming.md.
   223  // It is parsed from the target string that gets passed into Dial or DialContext
   224  // by the user. And gRPC passes it to the resolver and the balancer.
   225  //
   226  // If the target follows the naming spec, and the parsed scheme is registered
   227  // with gRPC, we will parse the target string according to the spec. If the
   228  // target does not contain a scheme or if the parsed scheme is not registered
   229  // (i.e. no corresponding resolver available to resolve the endpoint), we will
   230  // apply the default scheme, and will attempt to reparse it.
   231  //
   232  // Examples:
   233  //
   234  // - "dns://some_authority/foo.bar"
   235  //   Target{Scheme: "dns", Authority: "some_authority", Endpoint: "foo.bar"}
   236  // - "foo.bar"
   237  //   Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "foo.bar"}
   238  // - "unknown_scheme://authority/endpoint"
   239  //   Target{Scheme: resolver.GetDefaultScheme(), Endpoint: "unknown_scheme://authority/endpoint"}
   240  type Target struct {
   241  	// Deprecated: use URL.Scheme instead. 使用`target.GetScheme()`代替。
   242  	Scheme string
   243  	// Deprecated: use URL.Host instead. 使用`target.GetAuthority()`代替。
   244  	Authority string
   245  	// Deprecated: use URL.Path or URL.Opaque instead. The latter is set when
   246  	// the former is empty.
   247  	// 使用`target.GetEndpoint()`代替。
   248  	Endpoint string
   249  	// URL contains the parsed dial target with an optional default scheme added
   250  	// to it if the original dial target contained no scheme or contained an
   251  	// unregistered scheme. Any query params specified in the original dial
   252  	// target can be accessed from here.
   253  	URL url.URL
   254  }
   255  
   256  // GetScheme 获取Target的scheme: t.URL.Scheme
   257  //  `t.Scheme`已弃用,使用该方法获取`t.URL.Scheme`代替。
   258  //  优先使用t.URL.Scheme,如果为空,则使用t.Scheme
   259  func (t Target) GetScheme() string {
   260  	if t.URL.Scheme != "" {
   261  		return t.URL.Scheme
   262  	}
   263  	//goland:noinspection GoDeprecation
   264  	return t.Scheme
   265  }
   266  
   267  // GetAuthority 获取Target的authority: t.URL.Host
   268  //  `t.Authority`已弃用,使用该方法获取`t.URL.Host`代替。
   269  //  优先使用t.URL.Host,如果为空,则使用t.Authority
   270  func (t Target) GetAuthority() string {
   271  	if t.URL.Host != "" {
   272  		return t.URL.Host
   273  	}
   274  	//goland:noinspection GoDeprecation
   275  	return t.Authority
   276  }
   277  
   278  // GetEndpoint 获取Target的endpoint: t.URL.Path or t.URL.Opaque
   279  //  `t.Endpoint`已弃用,使用该方法获取`t.URL.Path`或`t.URL.Opaque`代替。
   280  //  优先使用`t.URL.Path`,如果为空,则使用`t.URL.Opaque`,
   281  //  `t.URL.Opaque`也为空,则使用`t.Endpoint`
   282  func (t Target) GetEndpoint() string {
   283  	endpoint := t.URL.Path
   284  	if endpoint == "" {
   285  		endpoint = t.URL.Opaque
   286  	}
   287  	endpoint = strings.TrimPrefix(endpoint, "/")
   288  	if endpoint != "" {
   289  		return endpoint
   290  	}
   291  	//goland:noinspection GoDeprecation
   292  	return t.Endpoint
   293  }
   294  
   295  // Builder creates a resolver that will be used to watch name resolution updates.
   296  type Builder interface {
   297  	// Build creates a new resolver for the given target.
   298  	//
   299  	// gRPC dial calls Build synchronously, and fails if the returned error is
   300  	// not nil.
   301  	Build(target Target, cc ClientConn, opts BuildOptions) (Resolver, error)
   302  	// Scheme returns the scheme supported by this resolver.
   303  	// Scheme is defined at https://github.com/grpc/grpc/blob/master/doc/naming.md.
   304  	Scheme() string
   305  }
   306  
   307  // ResolveNowOptions includes additional information for ResolveNow.
   308  type ResolveNowOptions struct{}
   309  
   310  // Resolver watches for the updates on the specified target.
   311  // Updates include address updates and service config updates.
   312  type Resolver interface {
   313  	// ResolveNow will be called by gRPC to try to resolve the target name
   314  	// again. It's just a hint, resolver can ignore this if it's not necessary.
   315  	//
   316  	// It could be called multiple times concurrently.
   317  	ResolveNow(ResolveNowOptions)
   318  	// Close closes the resolver.
   319  	Close()
   320  }
   321  
   322  // UnregisterForTesting removes the resolver builder with the given scheme from the
   323  // resolver map.
   324  // This function is for testing only.
   325  func UnregisterForTesting(scheme string) {
   326  	delete(m, scheme)
   327  }