resolver

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2024 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package resolver provides functionality for custom name resolution. Name resolution is the process of resolving service or domain names into one or more addresses -- where an address is a host:port (and optionally custom metadata) of a server that provides the service.

It contains the core interface (Resolver) that can be implemented to create a custom name resolution strategy. The interface is general enough that it can support any form of resolver, including ones that are backed by push mechanisms (like "watching" nodes in ZooKeeper or etcd or "watching" resources in Kubernetes).

Default Implementation

This package contains a default implementation that uses periodic polling via a ResolveProber. The one prober implementation included uses DNS to query addresses for a name using a net.Resolver.

To create a new resolver implementation that uses periodic polling, you need only implement the ResolveProber interface and use your implementation with NewPollingResolver. To create a more sophisticated implementation, you would need to implement the Resolver interface, which creates a new task for each service or domain that a client needs.

Subsetting

Subsetting can be achieved via a Receiver decorator that intercepts the addresses, selects a subset, and sends the subset to the underlying Receiver.

This decorator pattern is implemented by RendezvousHashSubsetter, which is a Resolver decorator. When the resolver's New method is called, it wraps the given Receiver with a decorator that computes the subset using rendezvous-hashing. It then passes that decorated Receiver to the underlying Resolver.

For decorators that use resources (such as background goroutines) and need to be explicitly shut down to release those resources, the Resolver interface should be decorated, just as is done by RendezvousHashSubsetter. That way, any tasks created by the Resolver can also be decorated, in order to hook into their Close method. When the task for a corresponding Receiver is closed, the decorator should shut down and release any resources.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Address

type Address struct {
	// HostPort stores the host:port pair of the resolved address.
	HostPort string

	// Attributes is a collection of arbitrary key/value pairs.
	Attributes attribute.Values
}

Address contains a resolved address to a host, and any attributes that may be associated with a host/address.

type AddressFamilyPolicy added in v0.3.0

type AddressFamilyPolicy int

AddressFamilyPolicy is an option that allows control over the preference for which addresses to consider when resolving, based on their address family.

const (
	// PreferIPv4 will result in only IPv4 addresses being used, if any
	// IPv4 addresses are present. If no IPv4 addresses are resolved, then
	// all addresses will be used.
	PreferIPv4 AddressFamilyPolicy = iota

	// RequireIPv4 will result in only IPv4 addresses being used. If no IPv4
	// addresses are present, no addresses will be resolved.
	RequireIPv4

	// PreferIPv6 will result in only IPv6 addresses being used, if any
	// IPv6 addresses are present. If no IPv6 addresses are resolved, then
	// all addresses will be used.
	PreferIPv6

	// RequireIPv6 will result in only IPv6 addresses being used. If no IPv6
	// addresses are present, no addresses will be resolved.
	RequireIPv6

	// PreferIPv6 will result in only IPv6 addresses being used, if any
	// UseBothIPv4AndIPv6 will result in all addresses being used, regardless of
	// their address family.
	UseBothIPv4AndIPv6
)

type Receiver

type Receiver interface {
	// OnResolve is called when the set of addresses is resolved. It may be called
	// repeatedly as the set of addresses changes over time. Each call must always
	// supply the full set of resolved addresses (no deltas).
	OnResolve([]Address)
	// OnResolveError is called when resolution encounters an error. This can
	// happen at any time, including after addresses are initially resolved. But
	// the errors may be ignored after initial resolution.
	OnResolveError(error)
}

Receiver is a client of a resolver and receives the resolved addresses.

type RendezvousConfig

type RendezvousConfig struct {
	// NumBackends specifies the number of backends to select out of the set of
	// available hosts. This option is required.
	NumBackends int

	// SelectionKey specifies the key used to uniquely select hosts. This value
	// controls which hosts get selected, thus typically you set a unique value
	// for each program instance, using e.g. the machine host name. If not set,
	// a random string will be used.
	SelectionKey string

	// Hash provides a hash function to use. If unspecified, an implementation
	// of MurmurHash3 will be used.
	Hash hash.Hash32
}

RendezvousConfig represents the configuration options for use with NewRendezvous.

type ResolveProber

type ResolveProber interface {
	// ResolveOnce resolves the given target name once, returning a slice of
	// addresses corresponding to the provided scheme and hostname.
	// The second return value specifies the TTL of the result, or 0 if there
	// is no known TTL value.
	//
	// The resolved addresses should have ports if it is needed for the expected
	// target network. For example, in the common case of TCP, if the provided
	// hostPort string does not contain a port, a default port should be added
	// based on the scheme.
	ResolveOnce(
		ctx context.Context,
		scheme,
		hostPort string,
	) (
		results []Address,
		ttl time.Duration,
		err error,
	)
}

ResolveProber is an interface for types that provide single-shot name resolution.

type Resolver

type Resolver interface {
	// New creates a continuous resolver task for the given target name. When
	// the target is resolved into backend addresses, they are provided to the
	// given callback.
	//
	// As new result sets arrive (since the set of addresses may change over
	// time), the callback may be called repeatedly. Each time, the entire set
	// of addresses should be supplied.
	//
	// The resolver may report errors in addition to or instead of addresses,
	// but it should keep trying to resolve (and watch for changes), even in
	// the face of errors, until it is closed or the given context is cancelled.
	//
	// The refresh channel will receive signals from the client hinting that it
	// may need new results. For example, if the client runs out of healthy
	// hosts, it may call this method in order to try to find more healthy
	// hosts. This is particularly likely to happen during e.g. a rolling
	// deployment, wherein the entire pool of hosts could disappear within the
	// span of a TTL. This may be a no-op. The refresh channel will not be
	// closed until after Close() returns.
	//
	// The Close method on the return value should stop all goroutines and free
	// any resources before returning. After close returns, there should be no
	// subsequent calls to callbacks.
	New(
		ctx context.Context,
		scheme, hostPort string,
		receiver Receiver,
		refresh <-chan struct{},
	) io.Closer
}

Resolver is an interface for continuous name resolution.

func MinConnections added in v0.2.0

func MinConnections(other Resolver, minAddresses int) Resolver

MinConnections decorates the given resolver so it sends a set of addresses that has at least as many entries as the given minimum. If the given resolver provides a smaller set of addresses, it replicates those addresses until the give minimum is reached.

This will cause a client to effectively make redundant connections to the same address which is particularly useful when the addresses are virtual IPs, which actually have multiple servers behind them. This is appropriate for environments like Kubernetes (which uses virtual IPs for non-headless services) and for use with services that have layer-4 (TCP) proxies/load balancers in front of them.

To avoid "hot spotting", where one backend address gets more load than others, this always fully replicates the set. So it will always report at least minAddresses, but could report nearly twice as many: in the case where the set from the underlying resolver has minAddresses-1 entries, this will provide (minAddresses-1)*2 entries.

func NewDNSResolver

func NewDNSResolver(
	resolver *net.Resolver,
	policy AddressFamilyPolicy,
	ttl time.Duration,
) Resolver

NewDNSResolver creates a new resolver that resolves DNS names. The specified address family policy value can be used to require or prefer either IPv4 or IPv6 addresses. Note that because net.Resolver does not expose the record TTL values, this resolver uses the fixed TTL provided in the ttl parameter.

func NewPollingResolver

func NewPollingResolver(
	prober ResolveProber,
	defaultTTL time.Duration,
) Resolver

NewPollingResolver creates a new resolver that polls an underlying single-shot resolver whenever the result-set TTL expires. If the underlying resolver does not return a TTL with the result-set, defaultTTL is used.

func RendezvousHashSubsetter

func RendezvousHashSubsetter(resolver Resolver, options RendezvousConfig) (Resolver, error)

RendezvousHashSubsetter returns a Resolver that creates tasks that use rendezvous hashing to pick a randomly-distributed but consistent subset of k hosts. When provided the same selection key and k value, it will return the same addresses. When an address is removed, all of the requests that would have been directed to it will be distributed randomly to other addresses.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL