Package cluster provides code to manage cluster Membership. Membership can currently be managed statically (via explicit configuration of active) or dynamically (using HashiCorp's Serf project).
import go.pitz.tech/lib/cluster
type CancelWatch func()
CancelWatch is used to remove a watch from the cluster membership.
type Cluster struct {
}
Cluster handles the discovery and management of cluster members. It uses HashiCorp's Serf and MemberList projects to discover and track active given a join address.
func New(opts ...Option) *Cluster
New constructs a cluster given the provided options.
func (c *Cluster) Membership() *Membership
Membership returns the underlying membership of the cluster. Useful for obtaining a snapshot or for manipulating the entries used by the cluster during testing.
func (c *Cluster) Start(ctx context.Context) error
Start initializes and starts up the cluster.
type Config struct {
NoDiscovery
DNSDiscovery
GossipDiscovery
}
Config provides a common configuration structure for forming clusters. This can be done by specifying a concrete list of peers, a DNS name that's periodically resolved, or using a gossip protocol.
func (c *Config) Start(ctx context.Context, membership *Membership) error
Start controls which discovery mechanism is invoked based on the provided configuration.
type DNSDiscovery struct {
Name string `json:"dns_name" usage:"specify the dns name to resolve"`
ResolveInterval time.Duration `json:"dns_resolve_interval" usage:"how frequently the dns name should be resolved" default:"30s"`
}
DNSDiscovery uses DNS to resolve cluster membership. Currently, this implementation uses the default DNS resolver that comes with Go. I know that the serf library uses something beyond the default implementation, so it might be worth exploring this later on.
func (dns *DNSDiscovery) Start(ctx context.Context, membership *Membership) error
type Discovery interface {
// Start runs the discovery process. Implementations should block, regardless if they're filling or subscribing to
// the membership pool.
Start(ctx context.Context, membership *Membership) error
}
Discovery provides an abstraction that allows implementers to fill or discover changes to the underlying membership pool. For example, GossipDiscovery fills the membership pool with members found via HashiCorp's Serf implementation. The leaderless.Director package implements this interface to learn about changes in the underlying membership pool.
type GossipDiscovery struct {
JoinAddress string `json:"join_address" usage:"create a cluster dynamically through a single join address"`
Config *serf.Config `json:"-"`
}
GossipDiscovery uses HashiCorp's Serf library to discover nodes within the cluster. It requires both TCP and UDP communication to be available.
func (g *GossipDiscovery) Start(ctx context.Context, membership *Membership) error
type Membership struct {
}
Membership tacks a current list of active within the cluster. It can be populated manually (useful for testing) or using common discovery mechanisms.
func (m *Membership) Add(peers []string)
Add inserts the provided active into the cluster's active list. Operation should
be O( m log(n) )
where m = len(peers)
and n = len(m.active) + len(m.left)
.
func (m *Membership) Left(peers []string)
Left allows peers to temporarily leave the cluster, but still be considered part
of active membership. Operation should be O( m log(n) )
where m = len(peers)
and n = len(m.active) + len(m.left)
.
func (m *Membership) Majority() int
Majority computes a cluster majority. This returns a simple majority for the cluster.
func (m *Membership) Remove(peers []string)
Remove deletes the provided active from the cluster's peer list. Operation
should be O( m log(n) )
where m = len(peers)
and n = len(m.active) + len(m.left)
.
func (m *Membership) Snapshot() ([]string, int)
Snapshot returns a copy of the current peer list.
func (m *Membership) Watch() (<-chan MembershipChange, CancelWatch)
Watch allows others to observe changes in the cluster membership.
type MembershipChange struct {
Active []string
Left []string
Removed []string
}
MembershipChange describes how the cluster membership has changed to outside observers.
type NoDiscovery struct {
Peers []string `json:"peers" usage:"create a cluster using a static list of addresses"`
}
NoDiscovery uses a statically provided list of peers to fill Membership.
func (n *NoDiscovery) Start(ctx context.Context, membership *Membership) error
type Option func(cluster *Cluster)
Option defines how callers can customize aspects of the cluster.
func WithDiscovery(discovery Discovery) Option
WithDiscovery allows alternative peer discovery mechanisms to be plugged in.