-
Notifications
You must be signed in to change notification settings - Fork 58
Router Concurrency
The router is non-blocking in that:
- Reading and writing one session will never block another session.
- Writing to a session will not affect reading from that same session.
- Reading from a session will not affect writing to that same session.
This means that:
- Different publishers can dispatch concurrently to one subscriber.
- One publisher can dispatch concurrently to different subscribers.
- One publisher dispatches serially to one subscriber.
- Different callers can concurrently call a callee.
The nexus WAMP router operates as a set of concurrent processing stages, that does not block on I/O at any stage (src-client -> router/realm -> broker -> sendQueue -> dst-client). Messages received from clients are dispatched to the appropriate handlers for routing and are then written to the outbound message queues of the receiving clients. This way the router never delays processing of messages waiting for I/O with clients.
Router
Reaml1
sessions
invk <--- session1............(outHandler) <--------+
evt <--- session2............(outHandler) <-----+ |
evt <--- session3............(outHandler) <--+ | |
pub ---> session4........(inHandler) | | |
call ---> session5..(inHandler) | | | |
| |pub | | |
call| | | | |
| V | | |
Broker..........)..(Handler) | | |
subscribers | | | event | | |
*session2 | | +-----------+ | |
*session3 | +------------------+ |
| |
V invocation |
Dealer.......(Handler)----------------------+
callees
*session1
Roles
callee: session1
subscriber: session2, session3
publisher: session4
caller: session5
Each (xHandler) is a singe goroutine+channel that persists for the lifetime of the associated object. Therefore, order is preserved for messages between any two sessions regardless of goroutine scheduling order.
Broker and Dealer cannot dispatch an event to a new goroutine, because this would mean that messages bound for the same destination session would be sent in separate goroutines, and delivery order would be affected by goroutine scheduling order. Instead they dispatch to the receiving session's out channel+goroutine.
Broker and Dealer have their own handler goroutines to:
- Safely access subscription or call maps.
- Not make session's input-handler wait for Broker when it could be dispatching other messages to Dealer.
NOTE: Sessions have separate in (recv) and out (send) handlers so that processing incoming messages is not blocked while waiting for outgoing messages to finish being sent. Also, the router is not blocked waiting for a session to send a message to a client.
If there are too many messages sent to the same session before the session can consume them, the session's channel that the router is writing may become full and block. When this happens the broker or dealer will need to drop messages to be able to continue processing.
The current implementation drops messages in this situation. If a RPC invocation message is dropped, an error is returned to the caller.
This may be addressed by putting the outgoing messages on a dynamically sized output queue for the session. See: https://github.com/gammazero/bigchan. This approach was not chosen as dropping messages will not lead to unbounded memory use.
- Home
- Introduction
- Developer Reference Guide
- Operational Information
- System Design
- Additional Information