Messaging
Services communicates with surrounding world and each other by sending and receiving JSON messages over the message bus.
The API gateway will translate incoming HTTP requests into a subject and a fruster message which are posted on the message bus so inbound services may handle the request.
The message model itself allows any valid JSON to be sent but wraps the payload inside a predefined message model that includes additional meta data.
Message bus
The message bus is the backbone to which all services connect and is used to communicate with each other. Fruster uses NATS message bus, which is a lightweight and high performing message bus.
In the fruster the message bus handles services discovery, load balancing and message delivery.
A service within Fruster defines which subjects to subscribe to. When any request is sent that matches the subject the service will handle the request and (in most cases) return a response.
A lot of the ground work to interact with the message bus is wrapped into the library
fruster-bus
.
Message model
Apart from the data
attribute which holds the payload, a fruster message includes meta data to answer the following:
- Logging
- Which service sent this message?
- Which message sequence does this message belong to?
- Which transaction does this message belong to?
- User identification
- Who is the logged in user and which scopes does she have?
- Optional HTTP meta data (only available for HTTP requests and responses)
- HTTP headers
- Query params
- Path params
Property | Type | Required | Description |
---|---|---|---|
reqId | uuid | Yes | Is generated and set by the initiator of a request sequence (usually the API gateway) and passed on to all subsequent messages. Used for logging to group all messages in a message sequence. |
transactionId | uuid | Yes | Id of transaction (request + response = transaction). Used for logging. |
user | object | - | Logged in user, only set if a JWT token exists and has been decrypted. |
from | object | Yes* | Name and instance id of service that sent the message. |
data | any | - | Payload of message. |
status | number | Yes, for responses | HTTP status code of response. |
error | object | Yes, if error response | See below for error properties. |
error.id | uuid | Yes, if error response | A unique identifier for this particular occurrence of the problem |
error.code | string | Yes, if error response | Error code that describes the error, for example BAD_REQUESTS |
error.title | string | - | Human friendly text describing the error. Should be kept same for all instances of this error. |
error.detail | string | - | Human friendly text describing the error with details that relates to this particular instance of the error. |
method | string | Yes, if HTTP req | HTTP method of request. Only present in HTTP messages. |
path | string | Yes, if HTTP req | HTTP path. Only present in HTTP request messages. |
headers | object | - | HTTP headers of request/response, if any. Only present in HTTP messages. |
query | object | - | HTTP query params, if any. Only present in HTTP request messages. |
params | object | - | HTTP path params, if any. Only present in HTTP request messages. Is parsed and set by API Gateway. |
Example: HTTP request
{ "reqId": "bc42858e-0346-4c5d-8481-084ff9a0f4d1", "data": { "foo": "bar" }, "method": "POST", "path": "/foo/123", "params": { "id": "123" }, "transactionId": "237866da-3a46-4fa1-9f64-8eda0b1199de" }
Example: Error response
{ "reqId": "bc42858e-0346-4c5d-8481-084ff9a0f4d1", "status": 400, "error": { "id": "28420b97-9ccf-45de-8314-3505df5c3e17", "code": "BAD_REQUEST", "title": "Bad request" }, "transactionId": "237866da-3a46-4fa1-9f64-8eda0b1199de" }
Subjects
Subject is the address a message is published to similar to an URL path.
It is an alphanumeric string with dot .
delimiters where the dot is used
to define hierarchies.
A subject can be subscribed on by exact match (i.e. user.create
) or with
wildcards *
or >
(i.e. user.*
). Check out NATS protocol documentation for details.
HTTP message subject
The API Gateway will translate HTTP requests and responses into bus messages. The translation is made on format:
http.{GET|POST|PUT|DELETE}.{path with dot instead of slash}
Example:
GET /user => http.get.user