Repositório contendo o projeto desenvolvido do curso Arquitetura de Microsserviços: Padrão Saga Orquestrado, ministrado por mim para a plataforma Udemy.
Para acessar o curso na plataforma, basta acessar esta URL: https://www.udemy.com/course/arquitetura-de-microsservicos-padrao-saga-orquestrado/
- Tecnologias
- Ferramentas utilizadas
- Arquitetura Proposta
- Execução do projeto
- Acessando a aplicação
- Acessando tópicos com Redpanda Console
- Dados da API
- Java 17
- Spring Boot 3
- Apache Kafka
- API REST
- PostgreSQL
- MongoDB
- Docker
- docker-compose
- Redpanda Console
- IntelliJ IDEA Community Edition
- Docker
- Gradle
No curso, desenvolveremos a seguinte aquitetura:
Em nossa arquitetura, teremos 5 serviços:
- Order-Service: microsserviço responsável apenas por gerar um pedido inicial, e receber uma notificação. Aqui que teremos endpoints REST para inciar o processo e recuperar os dados dos eventos. O banco de dados utilizado será o MongoDB.
- Orchestrator-Service: microsserviço responsável por orquestrar todo o fluxo de execução da Saga, ele que saberá qual microsserviço foi executado e em qual estado, e para qual será o próximo microsserviço a ser enviado, este microsserviço também irá salvar o processo dos eventos. Este serviço não possui banco de dados.
- Product-Validation-Service: microsserviço responsável por validar se o produto informado no pedido existe e está válido. Este microsserviço guardará a validação de um produto para o ID de um pedido. O banco de dados utilizado será o PostgreSQL.
- Payment-Service: microsserviço responsável por realizar um pagamento com base nos valores unitários e quantidades informadas no pedido. Este microsserviço guardará a informação de pagamento de um pedido. O banco de dados utilizado será o PostgreSQL.
- Inventory-Service: microsserviço responsável por realizar a baixa do estoque dos produtos de um pedido. Este microsserviço guardará a informação da baixa de um produto para o ID de um pedido. O banco de dados utilizado será o PostgreSQL.
Todos os serviços da arquitetura irão subir através do arquivo docker-compose.yml.
Há várias maneiras de executar os projetos:
- Executando tudo via
docker-compose
- Executando tudo via
script
de automação que eu disponibilizei (build.py
) - Executando apenas os serviços de bancos de dados e message broker (Kafka) separadamente
- Executando as aplicações manualmente via CLI (
java -jar
ougradle bootRun
ou via IntelliJ)
Para rodar as aplicações, será necessário ter instalado:
- Docker
- Java 17
- Gradle 7.6 ou superior
Basta executar o comando no diretório raiz do repositório:
docker-compose up --build -d
Obs.: para rodar tudo desta maneira, é necessário realizar o build das 5 aplicações, veja nos passos abaixo sobre como fazer isto.
Basta executar o arquivo build.py
. Para isto, é necessário ter o Python 3 instalado.
Para executar, basta apenas executar o seguinte comando no diretório raiz do repositório:
python build.py
Será realizado o build
de todas as aplicações, removidos todos os containers e em sequência, será rodado o docker-compose
.
Para que seja possível executar os serviços de bancos de dados e Message Broker, como MongoDB, PostgreSQL e Apache Kafka, basta ir no diretório raiz do repositório, onde encontra-se o arquivo docker-compose.yml
e executar o comando:
docker-compose up --build -d order-db kafka product-db payment-db inventory-db
Como queremos rodar apenas os serviços de bancos de dados e Message Broker, é necessário informá-los no comando do docker-compose
, caso contrário, as aplicações irão subir também.
Para parar todos os containers, basta rodar:
docker-compose down
Ou então:
docker stop ($docker ps -aq)
docker container prune -f
Antes da execução do projeto, realize o build
da aplicação indo no diretório raiz e executando o comando:
gradle build -x test
Para executar os projetos com Gradle, basta entrar no diretório raiz de cada projeto, e executar o comando:
gradle bootRun
Ou então, entrar no diretório: build/libs
e executar o comando:
java -jar nome_do_jar.jar
Para acessar as aplicações e realizar um pedido, basta acessar a URL:
http://localhost:3000/swagger-ui.html
Você chegará nesta página:
As aplicações executarão nas seguintes portas:
- Order-Service: 3000
- Orchestrator-Service: 8080
- Product-Validation-Service: 8090
- Payment-Service: 8091
- Inventory-Service: 8092
- Apache Kafka: 9092
- Redpanda Console: 8081
- PostgreSQL (Product-DB): 5432
- PostgreSQL (Payment-DB): 5433
- PostgreSQL (Inventory-DB): 5434
- MongoDB (Order-DB): 27017
Para acessar o Redpanda Console e visualizar tópicos e publicar eventos, basta acessar:
Você chegará nesta página:
É necessário conhecer o payload de envio ao fluxo da saga, assim como os produtos cadastrados e suas quantidades.
Existem 3 produtos iniciais cadastrados no serviço product-validation-service
e suas quantidades disponíveis em inventory-service
:
- COMIC_BOOKS (4 em estoque)
- BOOKS (2 em estoque)
- MOVIES (5 em estoque)
- MUSIC (9 em estoque)
POST http://localhost:3000/api/order
Payload:
{
"products": [
{
"product": {
"code": "COMIC_BOOKS",
"unitValue": 15.50
},
"quantity": 3
},
{
"product": {
"code": "BOOKS",
"unitValue": 9.90
},
"quantity": 1
}
]
}
Resposta:
{
"id": "64429e987a8b646915b3735f",
"products": [
{
"product": {
"code": "COMIC_BOOKS",
"unitValue": 15.5
},
"quantity": 3
},
{
"product": {
"code": "BOOKS",
"unitValue": 9.9
},
"quantity": 1
}
],
"createdAt": "2023-04-21T14:32:56.335943085",
"transactionId": "1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519"
}
É possível recuperar os dados da saga pelo orderId ou pelo transactionId, o resultado será o mesmo:
GET http://localhost:3000/api/event?orderId=64429e987a8b646915b3735f
GET http://localhost:3000/api/event?transactionId=1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519
Resposta:
{
"id": "64429e9a7a8b646915b37360",
"transactionId": "1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519",
"orderId": "64429e987a8b646915b3735f",
"payload": {
"id": "64429e987a8b646915b3735f",
"products": [
{
"product": {
"code": "COMIC_BOOKS",
"unitValue": 15.5
},
"quantity": 3
},
{
"product": {
"code": "BOOKS",
"unitValue": 9.9
},
"quantity": 1
}
],
"totalAmount": 56.40,
"totalItems": 4,
"createdAt": "2023-04-21T14:32:56.335943085",
"transactionId": "1682087576536_99d2ca6c-f074-41a6-92e0-21700148b519"
},
"source": "ORCHESTRATOR",
"status": "SUCCESS",
"eventHistory": [
{
"source": "ORCHESTRATOR",
"status": "SUCCESS",
"message": "Saga started!",
"createdAt": "2023-04-21T14:32:56.78770516"
},
{
"source": "PRODUCT_VALIDATION_SERVICE",
"status": "SUCCESS",
"message": "Products are validated successfully!",
"createdAt": "2023-04-21T14:32:57.169378616"
},
{
"source": "PAYMENT_SERVICE",
"status": "SUCCESS",
"message": "Payment realized successfully!",
"createdAt": "2023-04-21T14:32:57.617624655"
},
{
"source": "INVENTORY_SERVICE",
"status": "SUCCESS",
"message": "Inventory updated successfully!",
"createdAt": "2023-04-21T14:32:58.139176809"
},
{
"source": "ORCHESTRATOR",
"status": "SUCCESS",
"message": "Saga finished successfully!",
"createdAt": "2023-04-21T14:32:58.248630293"
}
],
"createdAt": "2023-04-21T14:32:58.28"
}
Para conectar-se ao MongoDB via linha de comando (cli) diretamente do docker-compose, basta executar o comando abaixo:
docker exec -it order-db mongosh "mongodb://admin:123456@localhost:27017"
Para listar os bancos de dados existentes:
show dbs
Para selecionar um banco de dados:
use admin
Para visualizar as collections do banco:
show collections
Para realizar queries e validar se os dados existem:
db.order.find()
db.event.find()
db.order.find(id=ObjectId("65006786d715e21bd38d1634"))
db.order.find({ "products.product.code": "COMIC_BOOKS"})