-
Notifications
You must be signed in to change notification settings - Fork 6
MessageRouter
MessageRouter represents a node within a kino network. It is a gateway, to which all other kino components, ActorsHosts and MessageHubs, connect to send and receive messages. To allow message exchange between nodes, MessageRouters as well connect to each other.
ActorHost, MessageHub, MessageRouter and ClusterMonitor are components, which communicate not by direct method calls (even those within the same process), but rather by message exchange. kino functionality is built around NetMQ library as a transport layer for message passing. NetMQ provides different types of sockets, which might have an Identity set to them. This Identity uniquely points to an exact socket within a network and is a key technical detail for understanding the message routing. So, if we know the socket Identity of a MessageRouter or ActorHost or any other component, we can send a message to it.
In order the MessageRouter to be able to route any message in the network, it must know:
- all message types each of all locally connected ActorHosts or MessageHubs can process;
- all message types each of all remotely connected MessageRouters can process.
First is achieved by ActorHost sending a RegisterInternalMessageRouteMessage to MessageRouter, to which it is connected, every time an actor is assigned to ActorHost. For each pair of MessageIdentifier-MessageHandler from ActorHandlerMap, it takes MessageIdentifier and replaces the reference to the handler function (MessageHandler) with its socket Identity. Based on the information from this message, MessageRouter builds its InternalRoutingTable, collection of pairs MessageIdentifier-SocketIdentity.
Now, MessageRouter is taking a step further and for each pair of MessageIdentifier-SocketIdentity from InternalRoutingTable it replaces SocketIdentifier of ActorHost with its own external SocketIdentifier. These mappings are then sent with RegisterExternalMessageRouteMessage to all other routers in the kino network. Upon receive, routing information is added to ExternalRoutingTable of each MessageRouter.
This is how message routes are distributed across all the nodes.
-
Unicast message:
FIND local ActorHost or MessageHub that can handle the message IF exists send message to it ELSE FIND remote MessageRouter that can handle the message IF exists send message to it ELSE log unhandled message
-
Broadcast message:
FIND all local ActorHost or MessageHub that can handle the message IF exists send message to them IF broadcast message is sent from local Actor FIND all remote MessageRouter that can handle the message IF exists send message to them IF no local ActorHosts AND MessageHubs AND remote MessageRouters exist log unhandled message
-
Direct message:
IF message is Unicast FIND remote MessageRouter, set for the message as a ReceiverNode, which can handle the message IF exists send message to it ELSE log unhandled message ELSE Broadcast message
The sample code below shows how the instance MessageRouter could be constructed:
// Create Composer instance, which will build other kino components
var composer = new Composer();
// Resolve required dependencies
RouterConfiguration routerConfiguration = new RouterConfiguration {...};
ClusterMembershipConfiguration clusterMembershipConfiguration = new ClusterMembershipConfiguration {...};
IEnumerable<RendezvousEndpoint> rendezvousEndpoints = new []{new RendezvousEndpoint{...}, ...};
// Create an instance of your logger, which implements ILogger interface
ILogger logger = new MyLogger();
// New instance is created every time BuildMessageRouter() is called.
IMessageRouter messageRouter = composer.BuildMessageRouter(routerConfiguration,
clusterMembershipConfiguration,
rendezvousEndpoints,
logger);
// Start message processing
messageRouter.Start();
Please, notice, that MessageRouter should be started in your application code before any other kino component.