For internal communication between the parts within the AAS Service we mainly use a message broker.
We deciced for AMQP (v0.9.1) as our messaging protocol and deploy the open source RabbitMQ to handle the messaging.
(For an introduction about RabbitMQ exchanges and queues, routing keys and bindings see for instance this blog)
We seperate the message flow of incoming and outgoing messages by using two seperate topic exchanges:
The exchange ingress
for all incoming messages.
The exchange egress
for all outgoing messages.
An ingress receives a "I40 Interaction Message" and publishes it for any further processing to the internal message broker on the exchange topic ingress and with a routing key that is determined by the semanticProtocol
, receiverRoleName
, and type
parameter of the I40 message in the following way:
ingress.(semanticProtocol).(receiverRoleName).(type)
Any actor (Skill) wishing to receive incoming messages consumes a queue from the broker with a binding pattern that matches this key pattern.
Outgoing messages are handled in several steps.
At first, a skill publishes the outgoing message to the broker exchange egress with the message routing key egress.generic
since the skill and the message itself do not know the message receiver.
The endpoint-resolver consumes the payloads of the queue with binding pattern egress.generic
and retrieves the receivers of the message and their external endpoints from the endpoint-registry
.
The endpoint_resolver then republishes the message to the egress exchange with a different routing key depending on the transport protocol (http
or grpc
) in the following way:
egress.(protocol)
For a cloud target instance listening on HTTP for example, the message would be published to
egress.http
Any egress service can consume a queue on the egress exchange with a binding matching this routing pattern, to process and finally send the message accordingly.