vincenzocorso / spring-outbox-example

A sample implementation of the Outbox Pattern for microservice architectures.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Introduction

Often in a Microservice Architecture, a service must atomically update the database and send messages in order to avoid inconsistencies. A solution to this problem is given by the Outbox Pattern, which states that each service must insert messages into an outbox table/collection as part of the local transaction.

Implementation

To ensure that messages are sent to the message broker, this example use Debezium, which streams data changes to Kafka.

Debezium offers connectors for many databases such as MySQL, PostgreSQL, SQLServer, MongoDB, Cassandra and others. Some predefined Single Message Transformations (SMT) are offered by Debezium to define the structure of the messages sent to the message broker. However, this implementation use two custom SMT to ensure more flexibility.

In this example there are two services: Todos and Tasks. Each one offers a REST endpoints that creates a new aggregate and publishes an event. For simplicity each service handles its own events.

Other considerations

Implement this pattern for services which use relational databases is pretty straightforward. The problems raise with NoSQL databases which might not have a rich transactional model.

For example MongoDB introduced multi-document transactions only in version 4.0. If a database doesn't permit such operations, a possible solution might be to save outbox events in the aggregate. For example, in document-oriented databases a document can have a nested field which stores outbox events for the specific aggregate.

This implementation uses Mongo v4.4 and multi-document transactions. However, this can incur in greater performance costs as stated in the official documentation.

Try it

You must have Docker and Docker Compose installed.

Now from the root folder:

./gradlew build jibDockerBuild
docker-compose up --build
./register-all-connectors.sh # Register all the debezium connectors
./create-todo.sh # Send a request to the Todos Service
./create-task.sh # Send a request to the Tasks Service

You should see from logs that each service handled its own events.

About

A sample implementation of the Outbox Pattern for microservice architectures.


Languages

Language:Java 97.1%Language:Shell 2.2%Language:Dockerfile 0.7%