Seastar
High performance C++ framework for concurrent servers
Classes | Public Member Functions | Public Attributes | List of all members
seastar::rpc::protocol< Serializer, MsgType > Class Template Referencefinal

Detailed Description

template<typename Serializer, typename MsgType = uint32_t>
class seastar::rpc::protocol< Serializer, MsgType >

Defines a protocol for communication between a server and a client.

A protocol is defined by a Serializer and a MsgType. The Serializer is responsible for serializing and unserializing all types used as arguments and return types used in the protocol. The Serializer is expected to define a read() and write() method for each such type T as follows:

template <typename Output>
void write(const serializer&, Output& output, const T& data);

template <typename Input>
T read(const serializer&, Input& input, type<T> type_tag);  // type_tag used to disambiguate

Where Input and Output have a void read(char*, size_t) and write(const char*, size_t) respectively. MsgType defines the type to be used as the message id, the id which is used to identify different messages used in the protocol. These are also often referred to as "verbs". The client will use the message id, to specify the remote method (verb) to invoke on the server. The server uses the message id to dispatch the incoming call to the right handler. MsgType should be hashable and serializable. It is preferable to use enum for message types, but do not forget to provide hash function for it.

Use register_handler() on the server to define the available verbs and the code to be executed when they are invoked by clients. Use make_client() on the client to create a matching callable that can be used to invoke the verb on the server and wait for its result. Note that register_handler() also returns a client, that can be used to invoke the registered verb on another node (given that the other node has the same verb). This is useful for symmetric protocols, where two or more nodes all have servers as well as connect to the other nodes as clients.

Use protocol::server to listen for and accept incoming connections on the server and protocol::client to establish connections to the server. Note that registering the available verbs can be done before/after listening for connections, but best to ensure that by the time incoming requests are to be expected, all the verbs are set-up.

Configuration

TODO

Isolation

RPC supports isolating verb handlers from each other. There are two ways to achieve this: per-handler isolation (the old way) and per-connection isolation (the new way). If no isolation is configured, all handlers will be executed in the context of the scheduling_group in which the protocol::server was created.

Per-handler isolation (the old way) can be configured by using the register_handler() overload which takes a scheduling_group. When invoked, the body of the handler will be executed from the context of the configured scheduling_group.

Per-connection isolation (the new way) is a more flexible mechanism that requires user application provided logic to determine how connections are isolated. This mechanism has two parts, the server and the client part. The client configures isolation by setting client_options::isolation_cookie. This cookie is an opaque (to the RPC layer) string that is to be interpreted on the server using user application provided logic. The application provides this logic to the server by setting resource_limits::isolate_connection to an appropriate handler function, that interprets the opaque cookie and resolves it to an isolation_config. The scheduling_group in the former will be used not just to execute all verb handlers, but also the connection loop itself, hence providing better isolation.

There a few gotchas related to mixing the two isolation mechanisms. This can happen when the application is updated and one of the client/server is still using the old/new mechanism. In general per-connection isolation overrides the per-handler one. If both are set up, the former will determine the scheduling_group context for the handlers. If the client is not configured to send an isolation cookie, the server's resource_limits::isolate_connection will not be invoked and the server will fall back to per-handler isolation if configured. If the client is configured to send an isolation cookie but the server doesn't have a resource_limits::isolate_connection configured, it will use default_isolate_connection() to interpret the cookie. Note that this still overrides the per-handler isolation if any is configured. If the server is so old that it doesn't have the per-connection isolation feature at all, it will of course just use the per-handler one, if configured.

Compatibility

TODO

Template Parameters
Serializerthe serializer for the protocol.
MsgTypethe type to be used as the message id or verb id.

#include <seastar/rpc/rpc.hh>

Inheritance diagram for seastar::rpc::protocol< Serializer, MsgType >:
seastar::rpc::protocol_base

Classes

class  client
 Represents a client side connection. More...
 
class  server
 Represents the listening port and all accepted connections. More...
 

Public Member Functions

 protocol (Serializer &&serializer)
 
template<typename Func >
auto make_client (MsgType t)
 
template<typename Func >
auto register_handler (MsgType t, Func &&func)
 
template<typename Func >
auto register_handler (MsgType t, scheduling_group sg, Func &&func)
 
future unregister_handler (MsgType t)
 
void set_logger (std::function< void(const sstring &)> logger)
 
void set_logger (::seastar::logger *logger)
 Set a logger to be used to log messages.
 
const loggerget_logger () const
 
shared_ptr< rpc::server::connectionmake_server_connection (rpc::server &server, connected_socket fd, socket_address addr, connection_id id) override
 
bool has_handler (MsgType msg_id)
 
bool has_handlers () const noexcept
 

Public Attributes

friend server
 

Member Function Documentation

◆ has_handlers()

template<typename Serializer , typename MsgType = uint32_t>
bool seastar::rpc::protocol< Serializer, MsgType >::has_handlers ( ) const
inlinenoexcept

Checks if any there are handlers registered. Debugging helper, should only be used for debugging and not relied on.

Returns
true if there are, false if there are no registered handlers.

◆ make_client()

template<typename Serializer , typename MsgType >
template<typename Func >
auto seastar::rpc::protocol< Serializer, MsgType >::make_client ( MsgType  t)

Creates a callable that can be used to invoke the verb on the remote.

Template Parameters
FuncThe signature of the verb. Has to be either the same or compatible with the one passed to register_handler on the server.
Parameters
tthe verb to invoke on the remote.
Returns
a callable whose signature is derived from Func as follows: given Func == Ret(Args...) the returned callable has the following signature: future<Ret>(protocol::client&, Args...).

◆ make_server_connection()

template<typename Serializer , typename MsgType = uint32_t>
shared_ptr< rpc::server::connection > seastar::rpc::protocol< Serializer, MsgType >::make_server_connection ( rpc::server server,
connected_socket  fd,
socket_address  addr,
connection_id  id 
)
inlineoverridevirtual

◆ register_handler() [1/2]

template<typename Serializer , typename MsgType >
template<typename Func >
auto seastar::rpc::protocol< Serializer, MsgType >::register_handler ( MsgType  t,
Func &&  func 
)

Register a handler to be called when this verb is invoked.

Template Parameters
Functhe type of the handler for the verb. This determines the signature of the verb.
Parameters
tthe verb to register the handler for.
functhe callable to be called when the verb is invoked by the remote.
Returns
a client, a callable that can be used to invoke the verb. See make_client(). The client can be discarded, in fact this is what most callers will do as real clients will live on a remote node, not on the one where handlers are registered.

◆ register_handler() [2/2]

template<typename Serializer , typename MsgType >
template<typename Func >
auto seastar::rpc::protocol< Serializer, MsgType >::register_handler ( MsgType  t,
scheduling_group  sg,
Func &&  func 
)

Register a handler to be called when this verb is invoked.

Template Parameters
Functhe type of the handler for the verb. This determines the signature of the verb.
Parameters
tthe verb to register the handler for.
sgthe scheduling group that will be used to invoke the handler in. This can be used to execute different verbs in different scheduling groups. Note that there is a newer mechanism to determine the scheduling groups a handler will run it per invocation, see isolation_config.
functhe callable to be called when the verb is invoked by the remote.
Returns
a client, a callable that can be used to invoke the verb. See make_client(). The client can be discarded, in fact this is what most callers will do as real clients will live on a remote node, not on the one where handlers are registered.

◆ set_logger()

template<typename Serializer , typename MsgType = uint32_t>
void seastar::rpc::protocol< Serializer, MsgType >::set_logger ( std::function< void(const sstring &)>  logger)
inline

Set a logger function to be used to log messages.

Deprecated:
use the logger overload set_logger(::seastar::logger*) instead.

◆ unregister_handler()

template<typename Serializer , typename MsgType >
future seastar::rpc::protocol< Serializer, MsgType >::unregister_handler ( MsgType  t)

Unregister the handler for the verb.

Waits for all currently running handlers, then unregisters the handler. Future attempts to invoke the verb will fail. This becomes effective immediately after calling this function.

Parameters
tthe verb to unregister the handler for.
Returns
a future that becomes available once all currently running handlers finished.

The documentation for this class was generated from the following files: