Documentation ¶
Overview ¶
Package rpc implements zrepl daemon-to-daemon RPC protocol on top of a transport provided by package transport. The zrepl documentation refers to the client as the `active side` and to the server as the `passive side`.
Design Considerations ¶
zrepl has non-standard requirements to remote procedure calls (RPC): whereas the coordination of replication (the planning phase) mostly consists of regular unary calls, the actual data transfer requires a high-throughput, low-overhead solution.
Specifically, the requirements for data transfer is to perform a copy of an io.Reader over the wire, such that an io.EOF of the original reader corresponds to an io.EOF on the receiving side. If any other error occurs while reading from the original io.Reader on the sender, the receiver should receive the contents of that error in some form (usually as a trailer message) A common implementation technique for above data transfer is chunking, for example in HTTP: https://tools.ietf.org/html/rfc2616#section-3.6.1
With regards to regular RPCs, gRPC is a popular implementation based on protocol buffers and thus code generation. gRPC also supports bi-directional streaming RPC, and it is possible to implement chunked transfer through the use of streams.
For zrepl however, both HTTP and manually implemented chunked transfer using gRPC were found to have significant CPU overhead at transfer speeds to be expected even with hobbyist users.
However, it is nice to piggyback on the code generation provided by protobuf / gRPC, in particular since the majority of call types are regular unary RPCs for which the higher overhead of gRPC is acceptable.
Hence, this package attempts to combine the best of both worlds:
GRPC for Coordination and Dataconn for Bulk Data Transfer ¶
This package's Client uses its transport.Connecter to maintain separate control and data connections to the Server. The control connection is used by an instance of pdu.ReplicationClient whose 'regular' unary RPC calls are re-exported. The data connection is used by an instance of dataconn.Client and is used for bulk data transfer, namely `Send` and `Receive`.
The following ASCII diagram gives an overview of how the individual building blocks are glued together:
+------------+ | rpc.Client | +------------+ | | +--------+ +------------+ | | +---------v-----------+ +--------v------+ |pdu.ReplicationClient| |dataconn.Client| +---------------------+ +--------v------+ | label: label: | | zrepl_control zrepl_data | +--------+ +------------+ | | +--v---------v---+ | transportmux | +-------+--------+ | uses +-------v--------+ |versionhandshake| +-------+--------+ | uses +------v------+ | transport | +------+------+ | NETWORK | +------+------+ | transport | +------^------+ | uses +-------+--------+ |versionhandshake| +-------^--------+ | uses +-------+--------+ | transportmux | +--^--------^----+ | | +--------+ --------------+ --- | | | | label: label: | | | zrepl_control zrepl_data | | +-----+----+ +-----------+---+ | |netadaptor| |dataconn.Server| | rpc.Server | + | +------+--------+ | |grpcclient| | | |identity | | | +-----+----+ | | | | | +---------v-----------+ | | |pdu.ReplicationServer| | | +---------+-----------+ | | | | --- +----------+ +------------+ | | +---v--v-----+ | Handler | +------------+ (usually endpoint.{Sender,Receiver})
Index ¶
- func WithLoggers(ctx context.Context, loggers Loggers) context.Context
- type Client
- func (c *Client) Close()
- func (c *Client) DestroySnapshots(ctx context.Context, in *pdu.DestroySnapshotsReq) (*pdu.DestroySnapshotsRes, error)
- func (c *Client) ListFilesystemVersions(ctx context.Context, in *pdu.ListFilesystemVersionsReq) (*pdu.ListFilesystemVersionsRes, error)
- func (c *Client) ListFilesystems(ctx context.Context, in *pdu.ListFilesystemReq) (*pdu.ListFilesystemRes, error)
- func (c *Client) Receive(ctx context.Context, req *pdu.ReceiveReq, streamCopier zfs.StreamCopier) (*pdu.ReceiveRes, error)
- func (c *Client) ReplicationCursor(ctx context.Context, in *pdu.ReplicationCursorReq) (*pdu.ReplicationCursorRes, error)
- func (c *Client) ResetConnectBackoff()
- func (c *Client) Send(ctx context.Context, r *pdu.SendReq) (*pdu.SendRes, zfs.StreamCopier, error)
- func (c *Client) WaitForConnectivity(ctx context.Context) error
- type DialContextFunc
- type Handler
- type HandlerContextInterceptor
- type Logger
- type Loggers
- type Server
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client implements the active side of a replication setup. It satisfies the Endpoint, Sender and Receiver interface defined by package replication.
func (*Client) DestroySnapshots ¶
func (c *Client) DestroySnapshots(ctx context.Context, in *pdu.DestroySnapshotsReq) (*pdu.DestroySnapshotsRes, error)
func (*Client) ListFilesystemVersions ¶
func (c *Client) ListFilesystemVersions(ctx context.Context, in *pdu.ListFilesystemVersionsReq) (*pdu.ListFilesystemVersionsRes, error)
func (*Client) ListFilesystems ¶
func (c *Client) ListFilesystems(ctx context.Context, in *pdu.ListFilesystemReq) (*pdu.ListFilesystemRes, error)
func (*Client) Receive ¶
func (c *Client) Receive(ctx context.Context, req *pdu.ReceiveReq, streamCopier zfs.StreamCopier) (*pdu.ReceiveRes, error)
func (*Client) ReplicationCursor ¶
func (c *Client) ReplicationCursor(ctx context.Context, in *pdu.ReplicationCursorReq) (*pdu.ReplicationCursorRes, error)
func (*Client) ResetConnectBackoff ¶
func (c *Client) ResetConnectBackoff()
type DialContextFunc ¶
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server abstracts the accept and request routing infrastructure for the passive side of a replication setup.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
heartbeatconn/integration_test_variablereceiverate
This integration test exercises the behavior of heartbeatconn where the server is slow at handling the data received over the connection.
|
This integration test exercises the behavior of heartbeatconn where the server is slow at handling the data received over the connection. |
microbenchmark
microbenchmark to manually test rpc/dataconn perforamnce With stdin / stdout on client and server, simulating zfs send|recv piping ./microbenchmark -appmode server | pv -r > /dev/null ./microbenchmark -appmode client -direction recv < /dev/zero Without the overhead of pipes (just protocol perforamnce, mostly useful with perf bc no bw measurement) ./microbenchmark -appmode client -direction recv -devnoopWriter -devnoopReader ./microbenchmark -appmode server -devnoopReader -devnoopWriter
|
microbenchmark to manually test rpc/dataconn perforamnce With stdin / stdout on client and server, simulating zfs send|recv piping ./microbenchmark -appmode server | pv -r > /dev/null ./microbenchmark -appmode client -direction recv < /dev/zero Without the overhead of pipes (just protocol perforamnce, mostly useful with perf bc no bw measurement) ./microbenchmark -appmode client -direction recv -devnoopWriter -devnoopReader ./microbenchmark -appmode server -devnoopReader -devnoopWriter |
timeoutconn
package timeoutconn wraps a Wire to provide idle timeouts based on Set{Read,Write}Deadline.
|
package timeoutconn wraps a Wire to provide idle timeouts based on Set{Read,Write}Deadline. |
timeoutconn/internal/wireevaluator
a tool to test whether a given transport implements the timeoutconn.Wire interface
|
a tool to test whether a given transport implements the timeoutconn.Wire interface |
Package grpcclientidentity makes the client identity provided by github.com/zrepl/zrepl/daemon/transport/serve.{AuthenticatedListener,AuthConn} available to gRPC service handlers.
|
Package grpcclientidentity makes the client identity provided by github.com/zrepl/zrepl/daemon/transport/serve.{AuthenticatedListener,AuthConn} available to gRPC service handlers. |
example
This package demonstrates how the grpcclientidentity package can be used to set up a gRPC greeter service.
|
This package demonstrates how the grpcclientidentity package can be used to set up a gRPC greeter service. |
grpchelper
Package grpchelper wraps the adaptors implemented by package grpcclientidentity into a less flexible API which, however, ensures that the individual adaptor primitive's expectations are met and hence do not panic.
|
Package grpchelper wraps the adaptors implemented by package grpcclientidentity into a less flexible API which, however, ensures that the individual adaptor primitive's expectations are met and hence do not panic. |
Package netadaptor implements an adaptor from transport.AuthenticatedListener to net.Listener.
|
Package netadaptor implements an adaptor from transport.AuthenticatedListener to net.Listener. |
Package transportmux wraps a transport.{Connecter,AuthenticatedListener} to distinguish different connection types based on a label sent from client to server on connection establishment.
|
Package transportmux wraps a transport.{Connecter,AuthenticatedListener} to distinguish different connection types based on a label sent from client to server on connection establishment. |
Package versionhandshake wraps a transport.{Connecter,AuthenticatedListener} to add an exchange of protocol version information on connection establishment.
|
Package versionhandshake wraps a transport.{Connecter,AuthenticatedListener} to add an exchange of protocol version information on connection establishment. |