From 9ca39dcf7222f9df13691d9445343b9b53c57a3c Mon Sep 17 00:00:00 2001 From: David Wilson Date: Thu, 7 Sep 2017 17:31:57 +0530 Subject: [PATCH] Add Message Routing section to docs --- docs/howitworks.rst | 52 +++ docs/images/context-tree.graphml | 497 ++++++++++++++++++++++++ docs/images/context-tree.png | Bin 0 -> 11679 bytes docs/images/route.graphml | 637 +++++++++++++++++++++++++++++++ docs/images/route.png | Bin 0 -> 16786 bytes 5 files changed, 1186 insertions(+) create mode 100644 docs/images/context-tree.graphml create mode 100644 docs/images/context-tree.png create mode 100644 docs/images/route.graphml create mode 100644 docs/images/route.png diff --git a/docs/howitworks.rst b/docs/howitworks.rst index 45bf3cb4..54153f3c 100644 --- a/docs/howitworks.rst +++ b/docs/howitworks.rst @@ -395,6 +395,58 @@ presence of many machines, and would require manually splitting up the parts of Twisted that we would like to use. +Message Routing +--------------- + +At present routing is very simple, and assumes that it is impossible for a tree +of contexts to be constructed such that at least one of a context's indirect +parents will not know the ID of a target the context is attempting to +communicate with. + +When :py:class:`econtext.core.Router` receives a message, it first checks the +IDs associated with its directly connected streams for a potential route for +the message. If one of the streams matches, either because the stream directly +connects to the target ID, or the master has sent an ``ADD_ROUTE`` message +associating that stream with the target ID, then the message will be forwarded +down the tree using that stream. + +If the message does not match any ``ADD_ROUTE`` message or directly connected +stream, instead it is forwarded upstream, first to the context's parent, and +recursively by the each parent context in turn, until some tree node is reached +that knows how to forward the message back down the tree. + +When the master establishes a new context via an existing child context, it +takes care to send corresponding ``ADD_ROUTE`` messages to each indirect parent +up the tree. + + +Example +####### + +.. image:: images/context-tree.png + +In the diagram, when ``master`` is establishing a connection to +``sudo:node12b:webapp``, it must send ``ADD_ROUTE`` messages to ``rack12``, +``dc1``, and ``bastion``; `node12b` does not require an ``ADD_ROUTE`` message +since it has a stream directly connected to the new context. + +When ``sudo:node22a:webapp`` wants to send a message to +``sudo:node12b:webapp``, the message will be routed as follows: + +``sudo:node22a:webapp -> node22a -> rack22 -> dc2 -> bastion -> dc1 -> rack12 -> node12b -> sudo:node12b:webapp`` + +.. image:: images/route.png + + +Future +###### + +The current routing approach is incomplete, since routes to downstream contexts +are not propagated upwards when a descendant of the master context establishes +a new child context, but that is okay for now, since child contexts cannot +currently allocate new context IDs anyway. + + Differences Between Master And Slave Brokers ############################################ diff --git a/docs/images/context-tree.graphml b/docs/images/context-tree.graphml new file mode 100644 index 00000000..3ec973e3 --- /dev/null +++ b/docs/images/context-tree.graphml @@ -0,0 +1,497 @@ + + + + + + + + + + + + + + + + + + + + + + + master + + + + + + + + + + + + + + + + + bastion + + + + + + + + + + + + + + + + + dc1 + + + + + + + + + + + + + + + + + dc2 + + + + + + + + + + + + + + + + + rack11 + + + + + + + + + + + + + + + + + rack12 + + + + + + + + + + + + + + + + + node11a + + + + + + + + + + + + + + + + + node11b + + + + + + + + + + + + + + + + + node12a + + + + + + + + + + + + + + + + + node12b + + + + + + + + + + + + + + + + + node21a + + + + + + + + + + + + + + + + + node21b + + + + + + + + + + + + + + + + + node22a + + + + + + + + + + + + + + + + + node22b + + + + + + + + + + + + + + + + + rack21 + + + + + + + + + + + + + + + + + rack22 + + + + + + + + + + + + + + + + + sudo:node12b:webapp + + + + + + + + + + + + + + + + + sudo:node22a:webapp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/context-tree.png b/docs/images/context-tree.png new file mode 100644 index 0000000000000000000000000000000000000000..eb17ee8b5028937c9ffa62e15b7b1851bd076e6a GIT binary patch literal 11679 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 EAIFMai~s-t literal 0 HcmV?d00001 diff --git a/docs/images/route.graphml b/docs/images/route.graphml new file mode 100644 index 00000000..4cf55d1f --- /dev/null +++ b/docs/images/route.graphml @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + + + + + + + + + master + + + + + + + + + + + + + + + + + + bastion + + + + + + + + + + + + + + + + + + dc1 + + + + + + + + + + + + + + + + + + dc2 + + + + + + + + + + + + + + + + + + rack11 + + + + + + + + + + + + + + + + + + rack12 + + + + + + + + + + + + + + + + + + node11a + + + + + + + + + + + + + + + + + + node11b + + + + + + + + + + + + + + + + + + node12a + + + + + + + + + + + + + + + + + + node12b + + + + + + + + + + + + + + + + + + node21a + + + + + + + + + + + + + + + + + + node21b + + + + + + + + + + + + + + + + + + node22a + + + + + + + + + + + + + + + + + + node22b + + + + + + + + + + + + + + + + + + rack21 + + + + + + + + + + + + + + + + + + rack22 + + + + + + + + + + + + + + + + + + sudo:node12b:webapp + + + + + + + + + + + + + + + + + + sudo:node22a:webapp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/images/route.png b/docs/images/route.png new file mode 100644 index 0000000000000000000000000000000000000000..d535f847f616e3848bb7b6ccaa3ce7bf6e7043b5 GIT binary patch literal 16786 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 literal 0 HcmV?d00001