Health 🩺
As verificações de Health checks são usadas para verificar o estado de um serviço. Esse tipo de recurso é propício para ambientes de infraestrutura em nuvem onde processos automatizados mantêm o estado de nós de computação (kubernetes por exemplo).
Nesse contexto, essas verificações são usadas para determinar se um nó de computação precisa ser descartado/encerado e/ou eventualmente substituído por outra instância. Assim, o Health checks não se destina (embora possa ser usado) como uma solução de monitoramento de serviços para operadores humanos.
Por padrão, o Quarkus utiliza a extensão SmallRye Health como uma implementação da especificação Microprofile Health.
Configuração no Quarkus
Para se criar um projeto Quarkus com recursos de Health checks abra um terminal de digite (linux, unix):
mvn io.quarkus.platform:quarkus-maven-plugin:2.4.1.Final:create \
-DprojectGroupId=dev.pw2 \
-DprojectArtifactId=health \
-Dextensions="smallrye-health"
code health
Se você já tiver um projeto Quarkus e quiser instalar o smallrye-health
digite na raiz do projeto:
./mvnw quarkus:add-extension -Dextensions="smallrye-health"
Outra opção é adicionar no pom.xml a seguinte dependência:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
Implementação
A extensão smallrye-health
irá habilitar endpoints, são eles:
-
/q/health/live
- indica se o serviço está rodando (vivo). -
/q/health/ready
- informa se o serviço está pronto para atender às solicitações (requests). -
/q/health
- indica se o serviço está vivo e também pronto para atender às solicitações.
Os endpoints retornam um objeto JSON contendo duas propriedades:
-
status - o resultado geral de todos os procedimentos de verificação de saúde.
-
checks - uma série de verificações individuais.
Um exemplo dos dados retornados no endpoint /q/health
:
{
"status": "UP",
"checks": [
{
"name": "I'm alive",
"status": "UP"
},
{
"name": "Database connection health check",
"status": "UP",
"data": {
"key": "some information"
}
}
]
}
Uma classe que implementa uma verificação de health deve ser decorada com @ApplicationScoped
ou @Singleton
. Estas anotações fazem com que seja criado uma única instância de um bean que irá responder a todas as requisições de verificação de saúde. Se uma classe do bean não for decorada, então o escopo @Singleton
é usado automaticamente, no momento da utilização das anotações @Liveness
e @Readiness
. Observe o exemplo abaixo:
@Liveness
@Startup
public class Live implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Management is alive!");
}
}
Como você pode ver, os procedimentos de verificação de integridade são definidos por meio de beans que implementam a interface HealthCheck
e que são decorados com uma das anotações de verificação de integridade, tais como:
@Liveness
- faz com o que o bean responda no endpoint/q/health /live
e indique que o serviço está vivo(rodando).@Readiness
- faz com o que o bean responda no endpoint/q/health/ready
e indique que o serviço está pronto para receber requisições.@Startup
- faz com que o bean seja instanciado no início da aplicação.
Assim, para atender ao endpoint /q/health/ready
você pode implementar, por exemplo, a classe Ready.java
conforme o trecho de código abaixo:
@Readiness
public class Ready implements HealthCheck {
@Inject
@RestClient
PingRC service;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder response =
HealthCheckResponse.named(Ready.class.getName());
checkCatalogService(response);
return response.build();
}
private HealthCheckResponseBuilder checkCatalogService(
HealthCheckResponseBuilder response) {
if (service.ping().equals("Pong")) {
response.up().withData("CatalogService", "up");
}
return response;
}
}
Lembre-se de que a classe Ready
é um bean Singleton pois não foi anotada. 🚨 Uma observação interessante, javax.ejb.Singleton
são transacionais, porém, javax.inject.Singleton
não são, ou seja, não suportam acessos concorrentes.
No exemplo acima, a classe Ready
verifica se o serviço de catálogo está disponível. Para isso, a classe Ready
injeta um Rest Client chamado do serviço de catálogo chamado PingRC
. Assim, o método privado checkCatalogService
verifica se o serviço de catálogo está disponível e retorna um objeto HealthCheckResponseBuilder
com o status do serviço de catálogo. Logo, o método call
retorna um objeto HealthCheckResponse
com o status do serviço de catálogo.
A extensão smallrye-health
também pode criar uma URL /q/health-ui
para que você observe as verificações de saúde por meio de uma interface Web, conforme ilustra a Figura 1. A URL /q/health-ui
é habilita por padrão nos modos de desenvolvimento e teste, porém, pode ser explicitamente configurada para o modo de produção se a propriedade do Quarkus quarkus.smallrye-health.ui.enable=true
receber o valor true
.
http://localhost:8080/q/health-ui/
Figura 1 - Health UI
Código 💡
Um código de exemplo desse documento pode ser encontrado no Github:
git clone -b dev https://github.com/rodrigoprestesmachado/pw2
code pw2/exemplos/books
Exercício 🏋️
No projeto da rede social de empréstimo de livros, adicione um Health Check no serviço management para verificar se o serviço de usuários se encontra disponível. Como resolver: Crie um método no Web Service do serviço de usuários para verificar se o serviço está disponível e, por meio de um Rest Cliente, faça com que o serviço de management verifique se o serviço de usuários está disponível.
Referências 📚
-
Alex Soto Bueno; Jason Porter; Quarkus Cookbook: Kubernetes-Optimized Java Solutions. Editora: O’Reilly Media, 2020.
-
SMALLRYE HEALTH disponível em: https://quarkus.io/guides/smallrye-health
CC BY 4.0 DEED