Este projeto é um exemplo de uma solução de "e-commerce" usando padrões de arquitetura, com 2 principais, que são: SAGA with Choreography e Event Sourcing.
Ele foi criado visando 4 pilares.
-
Resiliência
Neste projeto foram usados alguns artifícios para manter a resiliência dos serviços, como:- Circuit Breaker:
- Uso do Redis para guardar cache de informações entre serviços.
- Comunicação assíncrona entre os serviços.
-
Mensageria
Com o objetivo de manter a máxima resiliência da solução e o mais alto nível possível de disponibilidade foi usado Kafka como um message broker o que permite a comunicação entre os serviços de maneira assíncrona. -
Gerenciamento de Configuração
No nosso cenário não foi possível uma implementação aprofundada por uma limitação na linguagem usada no serviço. De todo modo, foi implementado um exemplo de solução usando ETCD como serviço que responde chave/valor e o serviço de produtos capturando dados de comunicação com o Kafka através de uma chamada ao etcd. -
Service Discovery
No nosso cenário não foi identificado uma necessidade latente de possuirmos uma implementação deste pilar, pois nenhum serviço conversa com outro diretamente. Ou seja, como a comunicação entre os serviços é assíncrona, vimos que este pilar foi "atendido" quando ativamos o Kafka.
Entretando, uma maneira de atender a este pilar de maneira elegante seria migrar nosso projeto hoje em docker-compose para kubernetes que nos entregaria soluções de service disovery muito eficiente e de fácil configuração.
chmod +x start.sh
sh start.sh
curl -X POST "http://localhost:1001/categories" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"category\":{\"name\":\"Masculino Adulto\"}}"
curl -X POST "http://localhost:1001/products" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"product\":{\"name\":\"Camisa Azul\",\"value\":16.097,\"category_id\":1}}"
curl -X POST "http://localhost:1001/products" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"product\":{\"name\":\"Camisa Vermelha\",\"value\":11.30,\"category_id\":1}}"
Conferir produto postado no tópico do Kafka para montar um cache de itens no wishlist_service
e cart_service
curl -X GET "http://localhost:1001/categories/1/products?popular=false" -H "accept: application/json"
curl -X GET "http://localhost:1001/products/1" -H "accept: application/json"
curl -X GET "http://localhost:1001/products/2" -H "accept: application/json"
curl -X GET "http://localhost:1001/products?popular=false&q%5Bname_cont%5D=azul" -H "accept: application/json"
curl -X GET "http://localhost:1001/products/1" -H "accept: application/json"
curl -X GET "http://localhost:1001/categories/1/products?popular=true" -H "accept: application/json"
Conferir chaves criadas no Configuration Manager ETCD
docker-compose -f docker-compose-etcd.yml exec etcd /bin/sh -c "etcdctl --endpoints http://etcd:2379 get development/product_service --prefix"
curl -X POST "http://localhost:1002/wishlists" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"wishlist\":{\"client_id\":100}}"
curl -X POST "http://localhost:1002/wishlists/1/items" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"item\":{\"product_id\":1}}"
curl -X POST "http://localhost:1002/wishlists/1/items" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"item\":{\"product_id\":999}}"
Conferir item da lista de desejo postado no tópico do Kafka para montar um cache de itens no cart_service
curl -X POST "http://localhost:1006/carts/100/items" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"item\":{\"product_id\":2,\"amount\":3}}"
curl -X POST "http://localhost:1006/carts/100/items" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"item\":{\"product_id\":99,\"amount\":3}}"
curl -X POST "http://localhost:1006/carts/100/items" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"item\":{\"wishlist_item_id\":1,\"amount\":5}}"
Conferir item da lista de desejo postado no tópico do Kafka para ser removido da lista de desejo correspondente
curl -X GET "http://localhost:1002/wishlists/1/items" -H "accept: application/json"
curl -X POST "http://localhost:1004/orders/open" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"order\":{\"cart_client_id\":100}}"
curl -X POST "http://localhost:1004/orders/open" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"order\":{\"cart_client_id\":225}}"
Conferir que o pedido ao ser criado solicita o total de itens no carrinho para o serviço cart_service
Conferir a resposta do total de itens no carrinho feito pelo serviço cart_service
para o serviço order_service
Verificar o valor total e a quantidade total de itens no pedido, que são calculados com base no que há no carrinho
curl -X GET "http://localhost:1004/orders/1" -H "accept: application/json"
curl -X POST "http://localhost:1004/orders/1/freight" -H "accept: */*" -H "Content-Type: application/json" -d "{\"freight\":{\"zip_code\":\"02512000\"}}"
curl -X POST "http://localhost:1004/orders/1/freight" -H "accept: */*" -H "Content-Type: application/json" -d "{\"freight\":{\"zip_code\":\"02599999\"}}"
Conferir o retorno do serviço freight_service
postado no tópico referente ao pedido de cálculo de frete que será consumido pelo serviço order_service
CALCULATE_FREIGHT_REPLY_CHANNEL
curl -X GET "http://localhost:1004/orders/1" -H "accept: application/json"
curl -X POST "http://localhost:1003/tickets/open" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ticket\":{\"description\":\"Problema X Y Z\",\"client_id\":100,\"order_id\":1}}"
curl -X POST "http://localhost:1003/tickets/closed" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"ticket\":{\"id\":1}}"
curl -X POST "http://localhost:1004/orders/closed" -H "accept: application/json" -H "Content-Type: application/json" -d "{\"order\":{\"id\":1}}"
curl -X GET "http://localhost:1006/carts/100/items" -H "accept: application/json"
chmod +x stop.sh
sh stop.sh
- https://bitbucket.org/tadeu-barbosa-cbds/fiap-microservices-exercicios/src/master/
- http://stytex.de/blog/2016/01/18/spring-cloud-sidecar-applications/
- https://github.com/yammer/circuitbox
- https://github.com/jnunemaker/resilient
- https://medium.com/onebyte-llc/distributed-systems-configuration-management-using-apache-zookeeper-2121b231a4a4
- https://github.com/FlowerWrong/scc_ruby
- https://github.com/davissp14/etcdv3-ruby
- https://github.com/conduktor/kafka-stack-docker-compose
- https://github.com/zendesk/delivery_boy
- https://github.com/zendesk/ruby-kafka
- https://github.com/zendesk/racecar
- https://www.instaclustr.com/support/documentation/kafka/accessing-and-using-kafka/use-kafka-with-ruby
- https://blog.blueapron.io/developing-with-kafka-and-rails-applications-783799e13489
- https://medium.com/zendesk-engineering/kafka-on-ruby-fdab12302146
- https://peaonunes.medium.com/circuitbox-how-to-circuit-breaker-in-ruby-3413fd9789e6
- https://imasters.com.br/back-end/aprenda-a-aumentar-resiliencia-de-suas-aplicacoes-ruby