Mostly-transparent batching of remote messages in Erlang/Elixir cluster.
Features & Design
For high throughput use cases ErlangVM's default remote messaging may not be optimal. Messages that are not sensitive to latency can be sent in compressed batches to save network bandwidth and to reduce TCP overhead.
BatchedCommunication.cast/2,BatchedCommunication.call/3, etc. (which behave similarly toGenServer.cast/2,GenServer.call/3, etc.) are provided.Remote messages sent using
BatchedCommunicationare relayed to the following processes:- A
BatchedCommunication.Senderprocess on the sender node, which buffers messages for a while, (optionally) compresses it, and sends the batch to theReceiverprocess on the destination node. - A
BatchedCommunication.Receiverprocess on the receiver node, which decodes the received batch and dispatches messages to each destination process.
- A
There are 32
Senders and 32Receivers in each node (for concurrency within each node) and the actualSenderandReceiverprocesses are chosen by hash values of receiver node and sender node, respectively. Thus message passing usingBatchedCommunicationpreserves order of messages between each pair of processes (just as the original Erlang message passing does), since messages go through the same set ofSenderandReceiverprocesses.The following configuration parameters can be modified at runtime:
- maximum wait time before sending messages as a batch
- maximum number of accumulated messages (during wait time) in a batch
- whether to compress batched messages or not
Of course local messages (i.e., message sent within a single node) are delivered immediately, bypassing the batching mechanism described above.
Summary
Functions
Sends the same message to multiple destination processes.
Makes a synchronous request to the given destination process.
Sends an asynchronous message to the given destination process.
Changes whether to compress each batch of messages or not.
Sets maximum number of messages to accumulate in one batch.
Sets maximum wait time (in milliseconds) before sending messages as a batch.
Changes the process scheduling priority of senders and receivers.
Collect statistics of batches sent from this node to the specified node during the specified duration (in milliseconds).
Gets the current configurations.
Sends a reply to a client that has sent a synchronous request.
Sends message to the destination process dest with a batching mechanism.
Types
@type batch_stats() :: {n_messages :: pos_integer(), raw_bytes :: pos_integer(), sent_bytes :: pos_integer()}
@type configurations() :: %{ max_wait_time: pos_integer(), max_messages_per_batch: pos_integer(), compression: BatchedCommunication.Compression.t() }
@type message() :: any()
@type reply() :: any()
Functions
Sends the same message to multiple destination processes.
@spec call( dest(), message(), timeout() | {:clean_timeout, timeout()} | {:dirty_timeout, timeout()} ) :: reply()
Makes a synchronous request to the given destination process.
When you want to batch multiple messages to the same destination node,
you can use this function as a replacement for GenServer.call/3.
Sends an asynchronous message to the given destination process.
When you want to batch multiple messages to the same destination node,
you can use this function as a replacement for GenServer.cast/2.
@spec change_compression(BatchedCommunication.Compression.t()) :: :ok
Changes whether to compress each batch of messages or not.
Currently supported values are :gzip and :raw (no compression).
Defaults to :gzip.
@spec change_max_messages_per_batch(pos_integer()) :: :ok
Sets maximum number of messages to accumulate in one batch.
When a BatchedCommunication.Sender process has messages more than or equal to this maximum,
it immediately (i.e., without waiting for timer; see also change_max_wait_time/1) sends the messages in one batch.
Defaults to 100 messages.
@spec change_max_wait_time(pos_integer()) :: :ok
Sets maximum wait time (in milliseconds) before sending messages as a batch.
When a BatchedCommunication.Sender process receives a message for a particular destination node,
it starts a timer with the maximum wait time.
When the timer fires the accumulated messages are sent in one batch.
Defaults to 100 milliseconds.
@spec change_process_priority(:high | :normal | :low) :: :ok
Changes the process scheduling priority of senders and receivers.
By default processes run with :normal priority.
You can change the priority of all sender/receiver processes using this function.
See also :erlang.process_flag/2.
@spec collect_sending_stats(node(), pos_integer()) :: [batch_stats()]
Collect statistics of batches sent from this node to the specified node during the specified duration (in milliseconds).
Each element of the returned list is a 3-tuple that consists of
- number of messages in a batch
- byte size of the batch before comprression
- byte size of the batch after compression (this is equal to the previous one if
:rawcompression option is used)
@spec get_configurations() :: configurations()
Gets the current configurations.
Sends a reply to a client that has sent a synchronous request.
When you want to batch multiple messages to the same destination node,
you can use this function as a replacement for GenServer.reply/2.
Sends message to the destination process dest with a batching mechanism.