RabbitMQ Lab — VLibTour Group communication system
Introduction to the step
This page/step is about the use cases that are presented in Section 2.3 of the micro-project. The architectural entities that are concerned are the group communication system and the tourist application that are presented in Section 4 of the same document.
In this page/step, we initiate the construction of the group communication. Then, we integrate the group communication into the tourist application in a dedicated integration phase. In the next page, we add authentication to the group communication. And, in the last page, the focus is on the lobby room system.
Foreword
The group communication system is based on the event-based paradigm: every tourist application subscribes in order to be notified of the publications that contain positions of the other members of the group of the visit, and every tourist application periodically publishes the position of the tourist. We need a topic-based distributed event-based system: for instance, we propose that the binding and routing keys are of the form "producer.consumer.messageType". We have decided to use the RabbitMQ server to play the role of the group communication system. Therefore, the content of the step is to interact with the RabbitMQ server in client applications—i.e. tourist applications. More precisely, in this page, you implement the methods to connect to the RabbitMQ server, to publish, to set the consumer, and to start consuming messages; all these methods are in class VLibTourGroupCommunicationSystemProxy in Maven module vlibtour-tourist-application in directory vlibtour-applications. This proxy class is then used by delegation in class VLibTourVisitTouristApplication of the tourist application (in the same Maven module). The usage of the delegation pattern is for avoiding adding too many technical details (connection management, etc.) in the tourist application.
This page does not contain a definite step by step description of how to design the group communication of the micro-project. The description is not exhaustive: We only provide essential clues for a possible architecting of the AMQP infrastructure. Please refer to the tutorial lab for the explanations about the AMQP and RabbitMQ concepts, and for the corresponding code examples. For instance, in this step, we mainly make use of Step 5 of the tutorial—i.e. by mimicking the code of the classes EmitLogTopic and ReceiveLogsTopic in directory ExemplesRabbitMQ/RabbitMQ-Tutorial-Step5 of the examples.
Rationale for the group communication
- Rationale 1: We like very much the strategy for the management of privacy that is chosen and implemented by some products like Sen.se and that is presented in the press release "Sen.se réinvente les mamans avec un gadget connecté": "respect de la vie privée : toutes les données que vous fournissez à l'application sont à vous. Rien qu'à vous. Point final." Firstly, we propose that every visit of a tour by a group of tourists is managed using a dedicated group communication system. Therefore, there is one AMQP exchange per group communication system. Secondly, we do not introduce any stateful visit manager in the server part of the system. Therefore, the data that are exchanged during a visit are only stored by the tourist applications, except of course during the brokering of messages by the AMPQ exchange of the group communication system.
- Rationale 2: Following the end-to-end argument, if we want to manage the ordering of messages broadcast through the group communication system (FIFO ordering or causal ordering, or even total ordering), we do this ordering task in the AMQP clients, that is not by configuring some exchanges, queues, etc.
Group communication system
AMQP architecture of the system
The following figure presents an example of the AMQP infrastructure of the group communication. In this example, there are four users. Every user has a dedicated queue and communication takes place through an exchange of type topic. The choice of the topic type for the exchange is explained below.
Naming the AMQP elements
The name of the exchange, of the queues, and the binding keys are built to avoid name collisions with the other group communication systems (of the other visits, for other tours, and perhaps with the same participants):
- The name of the exchange is for instance computed as the concatenation of the identifier of the group and the identifier of the user that creates the group—i.e. the first tourist application that initiates the visit. In the figure, user1 has created the group.
- The name of a queue is for instance computed as the concatenation of the identifier of the tour with the identifier of the tourist application that is bound to the queue.
- We propose to structure the name of the binding and routing keys with the name of the source as the first word, the name of the addressee ("all" for broadcasting) as the second word. Another word can be added for instance to distinguish the "type" of the content (let us imagine that the group communication system can be further used for broadcasting positions, chating, etc.). This choice will allow you to send unicast message and broadcast messages, and to differentiate the data sent in different message types.
- In order to use binding and routing keys as previously described, the type of the exchange is topic.
Implementation of the proxy of the group communication of the tourist application
Use the source code of the fifth step of the tutorial lab on RabbitMQ: See directory RabbitMQ-Tutorial-Step5, and more particularly, classes EmitLogTopic and ReceiveLogsTopic for writing the proxy to interact with the group communication system—i.e. the AMQP broker, which serves as the group communication system.
The code of this proxy is in the vlibtour-tourist-application Maven module, which is a sub-module of the vlibtour-applications Maven module. More precisely, the client is the class named VLibTourGroupCommunicationSystemProxy. The class is "empty"; the objective of this step is to write it.
Here follows some hints for the implementation. These hints are listed for helping purpose only and they are illustrated in the figure that follows the list of hints:
- You implement a proxy for a client, the client being either a JUnit integration test class (namely, the VLibTourGroupCommunicationProxyIT class in package vlibtour.vlibtour_group_communication_proxy) or the tourist application (namely, the VLibTourVisitTouristApplication class in package vlibtour.vlibtour_tourist_application).
- The arguments of the constructor of VLibTourGroupCommunicationSystemProxy are the identifiers of the group, the tour, and the user. The constructor is responsible for instanciating a connection factory, opening a new connection to the RabbitMQ broker, creating a channel, and creating some of the AMQP entities of the architecture (exchange, etc.).
- A method publish is responsible for publishing a message with a given routing key. A client can use this method to publish for instance their location to the group.
- A method setConsumer(Consumer consumer [...]) is responsible for setting a DefaultConsumer. The prototype of setConsumer indicates that the consumer is created before the call to this method. Practically, the integration test class or the tourist application class that use the proxy will (1) instanciate the proxy, (2) create the consumer and implement the method Consumer::handleDelivery to consume for instance the positions of the other members of the group, and (3) set the consumer in the proxy by calling setConsumer. You should adapt the prototype of the method setConsumer: for instance, the queue and the bindings are either created in the constructor of the proxy or in method setConsumer, and if they are created in method setConsumer then you should provide the name of the queue and the bindings as arguments.
- A method startConsumption launches the consumption of messages by calling Channel::basicConsume on the channel to the RabbitMQ broker. The thread of the consumer that is set with setConsumer is started. A notification leads to the call of the Consumer::handleDelivery method of the consumer.
- A method close is responsible for closing the channel and the connection to the broker.
Here follows the sequence diagram of the creation of the Proxy to the Group Communication System (in the construction of the .
For testing your code, (1) implement some tests in JUnit integration test class VLibTourGroupCommunicationProxyIT, and (2) run the integration tests script of the tourist application, which runs the integration tests of the different proxies, including the proxy to the group communication system. The integration test script of the tourist application executes command mvn failsafe:integration-test failsafe:verify in directory vlibtour-applications/vlibtour-tourist-application, thus executing the tests in JUnit class VLibTourGroupCommunicationProxyIT: