Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Next improvement of the libp2p network transport #255

Open
dnkolegov opened this issue Oct 3, 2022 · 3 comments
Open

Next improvement of the libp2p network transport #255

dnkolegov opened this issue Oct 3, 2022 · 3 comments
Labels
ADR Issue that should lead to an ADR backlog To address eventually, not necessarily now enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed

Comments

@dnkolegov
Copy link
Contributor

The source is the comments of #230:

  1. Improve network transport #230 (comment)
  2. Improve network transport #230 (comment)
  3. Improve network transport #230 (comment)
@dnkolegov dnkolegov added enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed labels Oct 3, 2022
@matejpavlovic
Copy link
Contributor

@matejpavlovic
Copy link
Contributor

matejpavlovic commented Oct 11, 2022

Suggested general architecture

The networking module knows the current membership, i.e., which nodes (IDs and addresses) it is supposed to communicate with. For each such node, it maintains one incoming and one outgoing byte stream. Each outgoing byte stream is associated with its own Dispatcher component. Each incoming stream is associated with a Receiver component. A Receiver is created upon an incoming connection from another node, but only if that node is part of the membership. The networking module also keeps a limited number of TentativeReceivers for incoming connections that are not part of the membership, for the case the membership has not yet been updated.

Dispatcher

A Dispatcher is a component that has a thread-safe FIFO buffer, a stream for outgoing messages, and a goroutine constantly reading messages from the buffer and writing them to the stream.

Writing in the buffer never blocks and the buffer keeps the most recently added messages. Thus, writing to a full buffer results in the oldest message in the buffer being dropped. An easy way to implement such a buffer is a buffered Go channel. If the writer, in a select statement, fails to write to the channel, it performs one read (making space for the write) and then tries to write again (in which case success is guaranteed).

The Dispatcher goroutine is responsible for establishing the network connection and sending messages from the buffer to it. If the connection breaks, the Dispatcher goroutine re-establishes it and continues sending messages.

Receiver

A receiver is implemented as a connection hander function. Its first action is to check whether the incoming connection is from a node in the membership. If that is the case, the Receiver simply continues by reading and deserializeing messages from the network and writing them in the module's output channel as Mir events. If the source of the connection is not in the membership, the receiver registers itself as a TentativeReceiver.

TentativeReceiver

A TentativeReceiver is like a Receiver, but buffers a limited number of most recently received messages instead of writing them directly to the module's output channel. When the membership of known to the module is updated to include the TentativeReceiver's source node, the TentativeReceiver flushes its buffer to the output and continues as a regular Receiver.

When too many (determined by a configuration parameter) TentativeReceivers exist in the module, the least recently created TentativeReceiver is destroyed (and its incoming stream is closed) whenever a new TentativeReceiver is created.

Updating the membership

Whenever the membership is updated (by calling Connect), the module creates the corresponding dispatchers (that create the network connections in the background) and, if necessary, TentativeReceivers are converted to Receivers. When closing old connections, the corresponding Dispatchers and Receivers are destroyed.

@matejpavlovic
Copy link
Contributor

As a bonus, it would be even nicer to have this machinery abstracted and usable with any network transport (libp2p, grpc, raw TCP, ...) using an appropriate interface.

@matejpavlovic matejpavlovic added the ADR Issue that should lead to an ADR label Oct 11, 2022
@matejpavlovic matejpavlovic added the backlog To address eventually, not necessarily now label Apr 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ADR Issue that should lead to an ADR backlog To address eventually, not necessarily now enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants