A arquitetura do software foi construido conforme a arquitetura de microsserviços.
Os serviços foram baseados no pattern Database per Service. Os serviços atualizam as informações relevantes entre os bancos de dados através de mensagens.
Para a comunicação dos eventos dos serviços foi utilizado o Message Queue RabbitMQ.
- campaign-service: serviço relacionado a operações com as campanhas.
- team-service: serviço relacionado a operações com os times.
- customer-service: serviço relacionado a operações com os clientes.
- customer-campaign-service: serviço relacionado a operações com as campanhas dos clientes.
- naming-service: service discovery Netflix Eureka.
- api-gateway-service: api gateway Netflix Zuul.
Cada serviço conta com a documentação correspondente implementada no Swagger.
O projeto é contruido com o gerenciador de dependências Maven.
Execute os goals clean
e install
do maven para que seja testado, baixadas as dependências e gerado o executavel .jar
do projeto. O Projeto foi preparado para funcionar em módulos, sendo que somente uma execução desse comando na raiz do projeto seja necessária.
$ mvn clean install
Para facilitar o deploy do projeto está preparado para funcionar com o Docker. Cada projeto utiliza um container e os projetos são orquestrados com o Docker compose.
Utilizando o Docker Composer:
$ docker-compose up --build -d
O docker já sobe todos os sistemas necessários para o funcionamento, incluindo o banco de dados e o servidor de AMPQ.
Para suportar a tolerância a falhas foi utilizado o Circuit Breaker Hystrix. Quando o Feign não consegue realizar a conexão com o servidor, o Fallback do Hystrix trata o erro.
- Documentação: http://base_url:8765/service_name/swagger-ui.html (possivelmente a
base_url
será localhost)- customer-service: http://base_url:8765/customer-service/swagger-ui.html
- customer-campaign-service: http://base_url:8765/customer-campaign-service/swagger-ui.html
- team-service: http://base_url:8765/team-service/swagger-ui.html
- campaign-service: http://base_url:8765/campaign-service/swagger-ui.html
- Eureka: http://base_url:8761/
- API Gateway: http://base_url:8765
Para o teste de desempenho foi utilizado o Gatling. Utilizando 100 requests simultaneos, somente foi realizado no endpoint de cadastro e obtenção de campanha (por ser considerado o mais custoso).
================================================================================
---- Global Information --------------------------------------------------------
> request count 200 (OK=200 KO=0 )
> min response time 5 (OK=5 KO=- )
> max response time 11615 (OK=11615 KO=- )
> mean response time 2288 (OK=2288 KO=- )
> std deviation 3291 (OK=3291 KO=- )
> response time 50th percentile 164 (OK=164 KO=- )
> response time 75th percentile 3731 (OK=3731 KO=- )
> response time 95th percentile 9700 (OK=9700 KO=- )
> response time 99th percentile 11214 (OK=11214 KO=- )
> mean requests/sec 15.385 (OK=15.385 KO=- )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms 111 ( 56%)
> 800 ms < t < 1200 ms 8 ( 4%)
> t > 1200 ms 81 ( 41%)
> failed 0 ( 0%)
================================================================================
Inicialmente foi utilizado o H2. Porém após os testes de desempenho, testando para 100 conexões simultâneas foi constatado que não é possivel a sua utilização para essa quantidade de acessos. Então o banco de dados foi alterado para o MongoDB.
Em alguns endpoints trechos do código foi implementado o Cache com Spring para que melhore o tempo de resposta.
Foram implementados testes unitários nas regras de negócios referentes ao cadastro de novas campanhas, utilizando o Mockito para realizar os mocks das classes dependentes.
Os testes de integração foram implementados na API de Campanhas, também utilizando o Mockito para realizar os mocks das classes dependentes.
Foram indentificados problemas de concorrência para acessos simultâneos na API de Campanhas, especificamente o endpoint de cadastro de campanha, o qual conta com uma regra especifica que impede que campanhas terminem no mesmo dia.
Para solicionar o problema de concorrência, foi utilizado o sistema de Locks de maneira em que o método que aplica a regra seja executada de maneira atômica, através do syncronized
do Java.