mesh

package module
v0.0.0-...-02ce71e Latest Latest
Warning

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

Go to latest
Published: May 4, 2016 License: Apache-2.0 Imports: 18 Imported by: 0

README

mesh GoDoc Circle CI

Mesh is a tool for building distributed applications.

Mesh implements a gossip protocol that provide membership, unicast, and broadcast functionality with eventually-consistent semantics. In CAP terms, it is AP: highly-available and partition-tolerant.

Mesh works in a wide variety of network setups, including thru NAT and firewalls, and across clouds and datacenters. It works in situations where there is only partial connectivity, i.e. data is transparently routed across multiple hops when there is no direct connection between peers. It copes with partitions and partial network failure. It can be easily bootstrapped, typically only requiring knowledge of a single existing peer in the mesh to join. It has built-in shared-secret authentication and encryption. It scales to on the order of 100 peers, and has no dependencies.

Using

Mesh is currently distributed as a Go package. See the API documentation.

We plan to offer Mesh as a standalone service + an easy-to-use API. We will support multiple deployment scenarios, including as a standalone binary, as a container, as an ambassador or sidecar component to an existing container, and as an infrastructure service in popular platforms.

Developing

Mesh builds with the standard Go tooling. You will need to put the repository in Go's expected directory structure; i.e., $GOPATH/src/github.com/weaveworks/mesh.

Building

If necessary, you may fetch the latest version of all of the dependencies into your GOPATH via

go get -d -u -t ./...

Build the code with the usual

go install ./...

Testing

Assuming you've fetched dependencies as above,

go test ./...

Dependencies

Mesh is a library, designed to be imported into a binary package. Vendoring is currently the best way for binary package authors to ensure reliable, reproducible builds. Therefore, we strongly recommend our users use vendoring for all of their dependencies, including Mesh. To avoid compatibility and availability issues, Mesh doesn't vendor its own dependencies, and doesn't recommend use of third-party import proxies.

There are several tools to make vendoring easier, including gb, gvt, glide, and govendor.

Workflow

Mesh follows a typical PR workflow. All contributions should be made as pull requests that satisfy the guidelines, below.

Guidelines
  • All code must abide Go Code Review Comments
  • Names should abide What's in a name
  • Code must build on both Linux and Darwin, via plain go build
  • Code should have appropriate test coverage, invoked via plain go test

In addition, several mechanical checks are enforced. See the lint script for details.

Documentation

Index

Constants

View Source
const (
	// PeerNameFlavour is the type of peer names we use.
	PeerNameFlavour = "mac"

	// NameSize is the number of bytes in a peer name.
	NameSize = 6

	// UnknownPeerName is used as a sentinel value.
	UnknownPeerName = PeerName(0)
)
View Source
const (
	// Protocol identifies a sort of major version of the protocol.
	Protocol = "weave"

	// ProtocolMinVersion establishes the lowest protocol version among peers
	// that we're willing to try to communicate with.
	ProtocolMinVersion = 1

	// ProtocolMaxVersion establishes the highest protocol version among peers
	// that we're willing to try to communicate with.
	ProtocolMaxVersion = 2
)
View Source
const (
	// ProtocolHeartbeat identifies a heartbeat msg.
	ProtocolHeartbeat = iota
	// ProtocolReserved1 is a legacy overly control message.
	ProtocolReserved1
	// ProtocolReserved2 is a legacy overly control message.
	ProtocolReserved2
	// ProtocolReserved3 is a legacy overly control message.
	ProtocolReserved3
	// ProtocolGossip identifies a pure gossip msg.
	ProtocolGossip
	// ProtocolGossipUnicast identifies a gossip (unicast) msg.
	ProtocolGossipUnicast
	// ProtocolGossipBroadcast identifies a gossip (broadcast) msg.
	ProtocolGossipBroadcast
	// ProtocolOverlayControlMsg identifies a control msg.
	ProtocolOverlayControlMsg
)

Variables

View Source
var (
	// Port is the port used for all mesh communication.
	Port = 6783

	// ChannelSize is the buffer size used by so-called actor goroutines
	// throughout mesh.
	ChannelSize = 16
)

Functions

This section is empty.

Types

type Config

type Config struct {
	Host               string
	Port               int
	ProtocolMinVersion byte
	Password           []byte
	ConnLimit          int
	PeerDiscovery      bool
	TrustedSubnets     []*net.IPNet
}

Config defines dimensions of configuration for the router. TODO(pb): provide usable defaults in NewRouter

type Connection

type Connection interface {
	Remote() *Peer
	// contains filtered or unexported methods
}

Connection describes a link between peers. It may be in any state, not necessarily established.

type Gossip

type Gossip interface {
	// GossipUnicast emits a single message to a peer in the mesh.
	//
	// TODO(pb): rename to Unicast?
	//
	// Unicast takes []byte instead of GossipData because "to date there has
	// been no compelling reason [in practice] to do merging on unicast."
	// But there may be some motivation to have unicast Mergeable; see
	// https://github.com/weaveworks/weave/issues/1764
	//
	// TODO(pb): for uniformity of interface, rather take GossipData?
	GossipUnicast(dst PeerName, msg []byte) error

	// GossipBroadcast emits a message to all peers in the mesh.
	//
	// TODO(pb): rename to Broadcast?
	GossipBroadcast(update GossipData)
}

Gossip is the sending interface.

TODO(pb): rename to e.g. Sender

type GossipData

type GossipData interface {
	// Encode encodes the data into multiple byte-slices.
	Encode() [][]byte

	// Merge combines another GossipData into this one and returns the result.
	//
	// TODO(pb): does it need to be leave the original unmodified?
	Merge(GossipData) GossipData
}

GossipData is a merge-able dataset. Think: log-structured data.

type Gossiper

type Gossiper interface {
	// OnGossipUnicast merges received data into state.
	//
	// TODO(pb): rename to e.g. OnUnicast
	OnGossipUnicast(src PeerName, msg []byte) error

	// OnGossipBroadcast merges received data into state and returns a
	// representation of the received data (typically a delta) for further
	// propagation.
	//
	// TODO(pb): rename to e.g. OnBroadcast
	OnGossipBroadcast(src PeerName, update []byte) (received GossipData, err error)

	// Gossip returns the state of everything we know; gets called periodically.
	Gossip() (complete GossipData)

	// OnGossip merges received data into state and returns "everything new
	// I've just learnt", or nil if nothing in the received data was new.
	OnGossip(msg []byte) (delta GossipData, err error)
}

Gossiper is the receiving interface.

TODO(pb): rename to e.g. Receiver

type LocalConnection

type LocalConnection struct {
	OverlayConn OverlayConnection
	// contains filtered or unexported fields
}

LocalConnection is the local (our) side of a connection. It implements ProtocolSender, and manages per-channel GossipSenders.

func (*LocalConnection) Remote

func (conn *LocalConnection) Remote() *Peer

func (*LocalConnection) SendProtocolMsg

func (conn *LocalConnection) SendProtocolMsg(m protocolMsg) error

SendProtocolMsg implements ProtocolSender.

type LocalConnectionStatus

type LocalConnectionStatus struct {
	Address  string
	Outbound bool
	State    string
	Info     string
}

LocalConnectionStatus is the current state of a physical connection to a peer.

type Logger

type Logger interface {
	Printf(format string, args ...interface{})
}

Logger is a simple interface used by mesh to do logging.

type NullOverlay

type NullOverlay struct{}

NullOverlay implements Overlay and OverlayConnection with no-ops.

func (NullOverlay) AddFeaturesTo

func (NullOverlay) AddFeaturesTo(map[string]string)

AddFeaturesTo implements Overlay.

func (NullOverlay) Confirm

func (NullOverlay) Confirm()

Confirm implements OverlayConnection.

func (NullOverlay) ControlMessage

func (NullOverlay) ControlMessage(byte, []byte)

ControlMessage implements OverlayConnection.

func (NullOverlay) Diagnostics

func (NullOverlay) Diagnostics() interface{}

Diagnostics implements Overlay.

func (NullOverlay) DisplayName

func (NullOverlay) DisplayName() string

DisplayName implements OverlayConnection.

func (NullOverlay) ErrorChannel

func (NullOverlay) ErrorChannel() <-chan error

ErrorChannel implements OverlayConnection.

func (NullOverlay) EstablishedChannel

func (NullOverlay) EstablishedChannel() <-chan struct{}

EstablishedChannel implements OverlayConnection.

func (NullOverlay) PrepareConnection

PrepareConnection implements Overlay.

func (NullOverlay) Stop

func (NullOverlay) Stop()

Stop implements OverlayConnection.

type Overlay

type Overlay interface {
	// Enhance a features map with overlay-related features.
	AddFeaturesTo(map[string]string)

	// Prepare on overlay connection. The connection should remain
	// passive until it has been Confirm()ed.
	PrepareConnection(OverlayConnectionParams) (OverlayConnection, error)

	// Obtain diagnostic information specific to the overlay.
	Diagnostics() interface{}
}

Overlay yields OverlayConnections.

type OverlayConnection

type OverlayConnection interface {
	// Confirm that the connection is really wanted, and so the
	// Overlay should begin heartbeats etc. to verify the operation of
	// the overlay connection.
	Confirm()

	// EstablishedChannel returns a channel that will be closed when the
	// overlay connection is established, i.e. its operation has been
	// confirmed.
	EstablishedChannel() <-chan struct{}

	// ErrorChannel returns a channel that forwards errors from the overlay
	// connection. The overlay connection is not expected to be operational
	// after the first error, so the channel only needs to buffer a single
	// error.
	ErrorChannel() <-chan error

	// Stop terminates the connection.
	Stop()

	// ControlMessage handles a message from the remote peer. 'tag' exists for
	// compatibility, and should always be ProtocolOverlayControlMessage for
	// non-sleeve overlays.
	ControlMessage(tag byte, msg []byte)

	// DisplayName returns the user-facing overlay name.
	DisplayName() string
}

OverlayConnection describes all of the machinery to manage overlay connectivity to a particular peer.

type OverlayConnectionParams

type OverlayConnectionParams struct {
	RemotePeer *Peer

	// The local address of the corresponding TCP connection. Used to
	// derive the local IP address for sending. May differ for
	// different overlay connections.
	LocalAddr *net.TCPAddr

	// The remote address of the corresponding TCP connection. Used to
	// determine the address to send to, but only if the TCP
	// connection is outbound. Otherwise the Overlay needs to discover
	// it (e.g. from incoming datagrams).
	RemoteAddr *net.TCPAddr

	// Is the corresponding TCP connection outbound?
	Outbound bool

	// Unique identifier for this connection
	ConnUID uint64

	// Session key, if connection is encrypted; nil otherwise.
	//
	// NB: overlay connections must take care not to use nonces which
	// may collide with those of the main connection. These nonces are
	// 192 bits, with the top most bit unspecified, the next bit set
	// to 1, followed by 126 zero bits, and a message sequence number
	// in the lowest 64 bits.
	SessionKey *[32]byte

	// Function to send a control message to the counterpart
	// overlay connection.
	SendControlMessage func(tag byte, msg []byte) error

	// Features passed at connection initiation
	Features map[string]string
}

OverlayConnectionParams are used to set up overlay connections.

type Peer

type Peer struct {
	Name PeerName
	// contains filtered or unexported fields
}

Peer is a local representation of a peer, including connections to other peers. By itself, it is a remote peer.

func (*Peer) String

func (peer *Peer) String() string

String returns the peer name and nickname.

type PeerDescription

type PeerDescription struct {
	Name           PeerName
	NickName       string
	UID            PeerUID
	Self           bool
	NumConnections int
}

PeerDescription collects information about peers that is useful to clients.

type PeerName

type PeerName uint64

PeerName is used as a map key. Since net.HardwareAddr isn't suitable for that - it's a slice, and slices can't be map keys - we convert that to/from uint64.

func PeerNameFromBin

func PeerNameFromBin(nameByte []byte) PeerName

PeerNameFromBin parses PeerName from a byte slice.

func PeerNameFromString

func PeerNameFromString(nameStr string) (PeerName, error)

PeerNameFromString parses PeerName from a generic string.

func PeerNameFromUserInput

func PeerNameFromUserInput(userInput string) (PeerName, error)

PeerNameFromUserInput parses PeerName from a user-provided string.

func (PeerName) String

func (name PeerName) String() string

String encodes PeerName as a string.

type PeerShortID

type PeerShortID uint16

PeerShortID exists for the sake of fast datapath. They are 12 bits, randomly assigned, but we detect and recover from collisions. This does limit us to 4096 peers, but that should be sufficient for a while.

type PeerStatus

type PeerStatus struct {
	Name        string
	NickName    string
	UID         PeerUID
	ShortID     PeerShortID
	Version     uint64
	Connections []connectionStatus
}

PeerStatus is the current state of a peer in the mesh.

type PeerUID

type PeerUID uint64

PeerUID uniquely identifies a peer in a mesh.

type Peers

type Peers struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Peers collects all of the known peers in the mesh, including ourself.

func (*Peers) Descriptions

func (peers *Peers) Descriptions() []PeerDescription

Descriptions returns descriptions for all known peers.

func (*Peers) Fetch

func (peers *Peers) Fetch(name PeerName) *Peer

Fetch returns a peer matching the passed name, without incrementing its refcount. If no matching peer is found, Fetch returns nil.

func (*Peers) FetchByShortID

func (peers *Peers) FetchByShortID(shortID PeerShortID) *Peer

FetchByShortID returns a peer matching the passed short ID. If no matching peer is found, FetchByShortID returns nil.

func (*Peers) GarbageCollect

func (peers *Peers) GarbageCollect()

GarbageCollect takes a lock, triggers a GC, and invokes the accumulated GC callbacks.

func (*Peers) OnGC

func (peers *Peers) OnGC(callback func(*Peer))

OnGC adds a new function to be set of functions that will be executed on all subsequent GC runs, receiving the GC'd peer.

func (*Peers) OnInvalidateShortIDs

func (peers *Peers) OnInvalidateShortIDs(callback func())

OnInvalidateShortIDs adds a new function to a set of functions that will be executed on all subsequent GC runs, when the mapping from short IDs to peers has changed.

type Router

type Router struct {
	Config
	Overlay         Overlay
	Ourself         *localPeer
	Peers           *Peers
	Routes          *routes
	ConnectionMaker *connectionMaker
	// contains filtered or unexported fields
}

Router manages communication between this peer and the rest of the mesh. Router implements Gossiper.

func NewRouter

func NewRouter(config Config, name PeerName, nickName string, overlay Overlay, logger Logger) *Router

NewRouter returns a new router. It must be started.

func (*Router) Gossip

func (router *Router) Gossip() GossipData

Gossip yields the current topology as GossipData.

func (*Router) NewGossip

func (router *Router) NewGossip(channelName string, g Gossiper) Gossip

NewGossip returns a usable GossipChannel from the router.

TODO(pb): rename?

func (*Router) OnGossip

func (router *Router) OnGossip(update []byte) (GossipData, error)

OnGossip receives broadcasts of TopologyGossipData. It returns an "improved" version of the received update. See peers.ApplyUpdate.

func (*Router) OnGossipBroadcast

func (router *Router) OnGossipBroadcast(_ PeerName, update []byte) (GossipData, error)

OnGossipBroadcast receives broadcasts of TopologyGossipData. It returns the received update unchanged.

func (*Router) OnGossipUnicast

func (router *Router) OnGossipUnicast(sender PeerName, msg []byte) error

OnGossipUnicast implements Gossiper, but always returns an error, as a router should only receive gossip broadcasts of TopologyGossipData.

func (*Router) Start

func (router *Router) Start()

Start listening for TCP connections. This is separate from NewRouter so that gossipers can register before we start forming connections.

func (*Router) Stop

func (router *Router) Stop() error

Stop shuts down the router. In theory.

type Status

type Status struct {
	Protocol           string
	ProtocolMinVersion int
	ProtocolMaxVersion int
	Encryption         bool
	PeerDiscovery      bool
	Name               string
	NickName           string
	Port               int
	Peers              []PeerStatus
	UnicastRoutes      []unicastRouteStatus
	BroadcastRoutes    []broadcastRouteStatus
	Connections        []LocalConnectionStatus
	Targets            []string
	OverlayDiagnostics interface{}
	TrustedSubnets     []string
}

Status is our current state as a peer, as taken from a router. This is designed to be used as diagnostic information.

func NewStatus

func NewStatus(router *Router) *Status

NewStatus returns a Status object, taken as a snapshot from the router.

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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