Message Driven Architecture
Asyncronous and non-blocking. The sender does not actively wait for a response.
Advantages:
- Resources are freed immediatly.
- Reduced contention
- Messages can be queued for deleivery in case the receiver’s is offline. Provides a higher level of reliability.
Disavantages:
- Make transactions more difficult.
- How to manage long running transactions that span multiple microservices.
- Holding transactions open for long periods result in slow, brittle systems.
The role of syncronous messags:
- Can you acknowledge the message but process it asyncronously?
- The need for syncronous messages should be driven by domain requirements rather than technical convenience.
Sagas #
Represent long running transaction. Multiple requests are managed by a Saga.
Individual requests are run in sequence or in paralel.
How:
- Each request is paired with a compensating action.
- If any requests fails, compnesation actions are executed for all completed steps.
- Then the saga is completed with a failure.
- If compensation actions fails, then it is retried. This requires idempotency.
Timeouts in distributed systems:
-
Eitehr the request failed.
-
Either it was successful but the reply failed.
-
The request is still queued and may success or fail eventually.
Compensating actions != Rollbacks.
Rollback: implies the transaction has not completed which removes the evidence of the transaction. Compensation: Applied on top of a previously completed action. Evidence of the orignal action remains.
Disavantages:
- Coupled to the failures unless we can move regardless of that.
- Saga are often implemented using ackka actors and represented via Finite State Machine.
Two General Problem #
Illustrate the impossibility of reaching a concensus over an unreliable communication channel.
Delivery Guarantees #
- Exactly Once: Is not possible in the event of a network partition, or lost message. We never guarantee that the message was in-fact sent. Failure requires resending the message which creates potential duplicates. Reuqires storage on both ends: unreliable network (as always); timeouts.
- At most once - If a failure occur, no retries are done which means no duplications but there may be losses. Requires no storage of messages.
- At least once - Require a acknoledge and teh sender needs to store state to track whether the messsage was acknowledge. It ahs to be stored in a durable data store.
Exactly once can be simulated using at least once and idempotency.
Akka: at most once by default. Akka persistence has option to have at least once.
Messaging Patterns #
Publish Subscribe #
Decoupled. The only coupling is on the message format and possibily the location (e.g., url, exchange on the message broker). Complexity is hard to see as we do not know where the message comes from.
Point to point #
Dependencies more clear but coupling is higher. COmplexity is directly observable.
Examples #
Kafaka, RabbitMQ. Kafka allows point to point and pub/sub and we can even acknowledge once we finish processing.
Akka: Typically point to point messaging;Persistence Query: Pub/sub Lagom: Point to point communication between services. Messages broker API allow for pub/sub.