Repositório para resolução do desafio da empresa iFood em: https://github.com/ifood/ifood-backend-basic-test
- Java 11
- Spring Boot 2.x
- Resilience4j
- Spring Open Feign
docker build -t ifood-desafio-backend .
docker run -p 8080:8080 ifood-desafio-backend
A aplicação é uma API que consiste em basicamente dois endpoints que retornam informações respeito do clima:
GET /about -> Verifica se a aplicação está de pé.
GET /weather?city={cidade} -> Retorna as informações sobre o clima atual de acordo com a cidade.
Para obter as informações sobre o clima, a aplicação está integrada com a OpenWeatherMaps. Segue um exemplo do JSON de resposta:
{
"id": "1427e5cf-d58d-46ec-9981-22e0ae54f625",
"cityName": "São Paulo",
"temperature": {
"id": "1427e5cf-d58d-46ec-9981-22e0ae54f625",
"temperature": "288.64",
"temperatureMin": "287.09",
"temperatureMax": "289.36",
"feelsLike": "288.54",
"humidity": 88
},
"weatherDescription": "broken clouds",
"wind": {
"id": "1427e5cf-d58d-46ec-9981-22e0ae54f625",
"speed": "1.34",
"deg": "70",
"gust": "2.24"
},
"updatedAt": "2021-08-07T00:54:22.508761489"
}
As temperaturas estão na unidade Kelvin.
Para evitar que a aplicação faça requisições desnecessárias ao OpenWeatherMaps foi desenvolvido um sistema simples de Cache utilizando um SyncronizedHashMap, armazenando a cidade como key e o seu respetivo clima como value.
A cada três minutos o job de limpeza é executado. O job percorrerá todo o mapa verificando se há algum elemento no mapa cuja atualização esteja ultrapassada — considere um elemento como ultrapassado aquele cuja última atualização se deu a mais de 30 minutos da execução do job.
Os elementos encontrados serão excluídos do Mapa.
No desafio original foi sugerido a utilização da biblioteca de tolerância a falhas Hystrix. Entretanto, a Hystrix não está mais em desenvolvimento e para os novos projetos a sugestão é utilizar Resilience4, justamente o que foi feito neste projeto.
Uma das grandes vantagens da utilização do Resilience4j em comparação com o Hystrix é o fato do Resilience4j possuir apenas uma dependência externa (Vavr), enquanto o Hystrix possui várias dependências externas como Guava e Apache Commons. Para saber mais a respeito do Resilience4j, acesse: https://github.com/resilience4j/resilience4j#readme
Circuit Breaker é um padrão para prevenção de erros em cascata quando um serviço externo a nossa explicação está indisponível. Depois de um número de requisições mal-sucedidas, a aplicação irá rejeitar quaisquer outras requisições dentro de um determinado período.
O CircuitBreaker da aplicação possui as seguintes configurações:
CircuitBreakerConfig config = CircuitBreakerConfig
.custom()
.slidingWindowType(CircuitBreakerConfig.SlidingWindowType.COUNT_BASED)
.slidingWindowSize(4)
.slowCallRateThreshold(50.0f)
.slowCallDurationThreshold(Duration.ofSeconds(2))
.waitDurationInOpenState(Duration.ofSeconds(10))
.build();
O CircuitBreaker será ativado caso metade das requisições responderem num tempo maior que 2 segundos. A partir disso, o Breaker estará no estado de OPEN durante 10 segundos. Isso significa que qualquer requisição durante estes 10 segundos será rejeitadas automaticamente, lançando HttpClientErrorException com status 500 (INTERNAL_SERVER_ERROR).
- Pensar numa estrutura de Cache mais robusta a partir de uma biblioteca específica.
- Incluir mais ferramentas de tolerância a falhas, como retry, fallbacks e demais funcionalidades disponíveis no Resilience4j.
- Testes de carga para verificar o comportamento da aplicação lidando com requisições concorrentes (In Progress).
- Dockerizar a aplicação (DONE)