Health Check
Health Checks are important in platforms like Kubernetes because it allows the infrastructure to be aware of the state of the application.
There are two different types of health checks:
-
Liveness probes tell your platform if your application is running ok or not. When your liveness probe is down, your platform might restart your instance to guarantee that you have the minimum required amount of running instances in production.
-
Readiness probes tell your platform if your application is warm enough to reply to requests in a reasonable amount of time. Java applications, for example, might need some time to warm up, so the readiness probe should be up only when it’s ready to reply to a request in a timely manner. Checks that depend on other services should be implemented as readiness probes: if a remote service is down, restarting your application won’t fix the issue.
Invoke the /health endpoint
Just by adding the Health extension you’ll have a /q/health
endpoint providing a very trivial health check.
Run the following command:
curl localhost:8080/q/health
{
"status": "UP",
"checks": [
{
"name": "Database connections health check",
"status": "UP"
}
]
}
Notice that since we’re using the Hibernate and database extensions, Quarkus automatically added a readiness probe checking the status of our database connections.
You can modify the default path by adding the following property in applications.properties :
|
quarkus.smallrye-health.root-path=/health
Add a custom liveness probe
Create a new LivenessProbe
Java class in src/main/java
in the com.redhat.developers
package with the following contents:
package com.redhat.developers;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
@Liveness
public class LivenessProbe implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("I'm alive");
}
}
Add a custom readiness probe
In dev mode, all your heath checks are visible in health UI: http://localhost:8080/q/health-ui/.
Some extensions may provide default health checks, including that the extension will automatically register its health checks. For example, quarkus-agroal (that is used to manage Quarkus datasources) automatically registers a readiness health check that will validate each datasource.
Since the readiness of the database is already assessed just by adding those extensions, we should look into defining health checks for other dependencies that we have.
As we depend on the availability of https://fruityvice.com, let’s create a new ReadinessProbe
to assess its availability prior to using it.
We will define a new Java class in src/main/java
in the com.redhat.developers
package with the following contents:
package com.redhat.developers;
import io.smallrye.health.checks.UrlHealthCheck;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.Readiness;
import javax.enterprise.context.ApplicationScoped;
import javax.ws.rs.HttpMethod;
@ApplicationScoped
public class CustomHealthCheck {
@ConfigProperty(name = "com.redhat.developers.FruityViceService/mp-rest/url")
String externalURL;
@Readiness (1)
HealthCheck checkURL() {
return new UrlHealthCheck(externalURL+"/api/fruit/banana") (2)
.name("ExternalURL health check").requestMethod(HttpMethod.GET).statusCode(200);
}
}
1 | Annotate the method with org.eclipse.microprofile.health.Readiness to signal its implementation. |
2 | UrlHealthCheck checks if host is reachable using a Http URL connection. |
Invoke the /health endpoint with custom probes
Run the following command:
curl localhost:8080/health
{
"status": "UP",
"checks": [
{
"name": "I'm alive",
"status": "UP"
},
{
"name": "ExternalURL health check",
"status": "UP",
"data": {
"host": "GET https://fruityvice.com/api/fruit/banana"
}
},
{
"name": "Database connections health check",
"status": "UP"
}
]
}
You can see that the /health
endpoint consolidates information from both the liveness and readiness probes.
Invoke the liveness endpoint
Run the following command:
curl localhost:8080/health/live
{
"status": "UP",
"checks": [
{
"name": "I'm alive",
"status": "UP"
}
]
}
You can see that the liveness endpoint only returns information about the liveness probes.
Invoke the readiness endpoint
Run the following command:
curl localhost:8080/health/ready
{
"status": "UP",
"checks": [
{
"name": "ExternalURL health check",
"status": "UP",
"data": {
"host": "GET https://fruityvice.com/api/fruit/banana"
}
},
{
"name": "Database connections health check",
"status": "UP"
}
]
}
You can see that the readiness endpoint only returns information about the readiness probes.