Andre's Blog

20170815 CISystem Architecture Specification 1 - Communication



It is a long time ago I wrote the requirement specification for CISystem.

CISystem will be a client-server-network-application implemented in Java.

Now I have finished the architecture specification for the whole communication between the network nodes and between the threads within the the nodes.

This specification covers only the main part of CISystem.

I will specify how to implement the missing requirements in future posts, that's why I have started a new mini series of posts with this one.

In this post I want to explain

Design Decisions

Some ideas which I had described in previous posts have changed, e.g. that two nodes have to roll dices to decide which socket connection will be closed to have only one socket connection between two nodes. I still think its a good idea to do it like that, but I don't want to focus on optimization before I have running implementation.

My idea is to maximize the amount of parallel executed code and parallel communication by having a thread for every communicating object and to let the objects communicate via different lists, which shall reduce the amount of blocked threads by increasing the channels for communication. The synchronization of the threads will be done synchronizing on these communication lists.

My assumptions are

  1. Java threads run in parallel if there is a core available for every thread
  2. Synchronizing on different lists is better than to synchronize on one list as this would block parallel communication between two nodes where both could be reading or writing at the same time or even worse if all threads would synchronize on the same list.

This leads me to my first four design decisions.

    Design Decision 1 :

    Communication shall always be bidirectional using two lists.

An object writes to one list and reads from the other list.

    Design Decision 2 :

    Every class shall have only one purpose.

Following the SOLID principles means for the architecture to follow the Single Responsibility principle.

There will application, resource and communication related classes.

In combination with Design Decision 1 this means several objects can communicate in parallel, because they block only the list they write or read.

The implementation of Design Decision 1 is explained below in Communication Between Threads.

The implementation of Design Decision 2 is explained below in Overview Of Threads And Their Connections.

    Design Decision 3 :

    All communicating objects shall use the same type for messages, so all communication lists have the same type.

I call the messages pakets and their class CIPaket.

A CIPaket has a map.

To give you a better idea which data will be send around, I list the description of those keys I have already planned and give you some examples for their usage in the lower level of the enumeration.

Most likely the real keys and maybe some of the values will be numbers representing the position of a a key string in a Java enumeration, to reduce the need of network bandwidth.

I just mention this here to explain why I cannot show you the final Key/Value list here.

This shall just make it easier to understand the communication :

What this means becomes clear when reading about the other thread kinds.

    Design Decision 4 :

    The nodes shall act like in a classic client-server-system but the network shall be fully interconnected.

The current server node is called active server.

All other nodes run their server applications in reading or recording mode.

All server actions are recorded by the server applications of all other nodes including a priority list who would be the next active server, so that every node can be the next active server if all other nodes in the list before it go down.

Network Communication

The network communication will be implemented with sockets.

Each node will be connected with every other node.

The connection will be bidirectional, every communicating object will read on one socket and write on an other socket.

Connection breaks will be detected by exceptions and the information about the breakdown will be distributed to all other nodes.

This is how the objects used for implementing the network communication will be connected :

Object connections for network communication

Communication Between Threads

Communicating objects are connected via two lists for reading and writing in parallel, they synchronize on these lists.

A communication object uses objects with these two lists as communication channels :

public final List<CIPaket> toObject
public final List<CIPaket> fromObject

A communication object reads synchronized toObject and writes synchronized fromObject.

It's connected partner uses the toObject list for writing and fromObject for reading.

A reader always clears the list it has consumed.

Overview Of Threads And Their Connections

This overview shows you which thread kinds will be populating a node and how they are connected :

Overview of threads

The Network Layer

A node has network layer threads, which do the whole communication with the other nodes.

Thread : Network Layer - Socket Master

The socket server thread listens to nodes requesting to connect and starts new socket client threads.

Thread : Network Layer - Socket Client

Socket Client threads have the duty to distribute the pakets to the whole network and to drop them when the paket id is already known from previous processing.

The network layer always sends all messages to all nodes, to enable every node as next server.

A fact : A client can always answer and grant access to any master when there is always only one server at the same time. We will come back to this point later.

A node processes always all new pakets by passing them to the paket layer

Here you can see the connections between Socket Server and Socket Client and between two Socket Clients :

Network communication

Thread : Paket Layer

The paket layer passes the pakets to the correct server application and depending on the paket to a client application or resource pool.

Thread : Server Application

Server applications have the modes active and reading. They request resources and tell client applications to use them.

There can be different server applications, so you don't have to implement the client-server-protocol for all client applications in one server application.

All active server applications must be on the same node, all server applications on all other nodes are just reading.

That's why I wrote, a client can always work for every server if there is only one master active at a time.

Thread : Client Application

Client applications work for the server applications with resources blocked by the server application.

Thread : Resource Pool

The resource pools implement the provision and blocking of local resources. they provide resources to the server applications and answer queries from client applications if resources are really blocked for them.

How It Works Or What It Does

Let's assume we have this setup

Example Setup

which is

The information flow is now following the arrows :

  1. Server aplication at A requests a resource from the resource pool at B
  2. The resource pool at B grants the usage of the resource to the server application at A
  3. The server application at A requests the client application at B to use the resource at B
  4. The client application at B verifies that the resource at B is blocked for this access
  5. The resource pool at B achnowledges that the resource is available for this access
  6. The client application at B performs the access and sends the result to the server application at A
  7. The server application at A receives the result

I do not mention the reading server application at node B, but both requests in 1. and 3. and the result of the access in 7. are stored as well in the same type of server application at node B, so that when node A goes down, node B can take over.

I am very excited to start with the implementation.

In parallel I want to figure out how to visualize the coverage of the requirements, there are different options :

  1. List the requirements together with the architecture specification in a table. This would give me additional space to explain why a design decision and its implementation idea covers a requirement. On the other hand it would be another document, I would repeat my self in writing down things I have already described and I think it is not the user friendliest way to give it to you.
  2. Set links between the requirements and the architecture specification in both directions. This would be easy to use but where shall I put the explanation why a design decision covers a requirement? In both documents? Then I would repeat myself and that would be planned, which feels even more funny.

I will find a solution.

Page Updates :

20170902 : updated the example graphic, the socket thread labels send/receive were missing

Select where to go ...

The Blog
My Technical Blogs
Blogs Of Friends