Health checks for microservices
A health check is a special REST API implementation that you can use to validate the status of a microservice and its dependencies. With MicroProfile Health, microservices can self-check their health and publish their overall status to a defined endpoint.
A health check can assess anything that a microservice needs, including dependencies, system properties, database connections, endpoint connections, and resource availability. The overall status of the microservice depends on whether all the configured health checks pass.
A microservice is considered available and reports an UP
status if all the configured health checks are successful. If one or more health checks fail, the microservice is considered unavailable and reports a DOWN
status. Services can report their availability to a defined endpoint by implementing the API that is provided by MicroProfile Health. A service orchestrator can use these status reports to decide how to manage and scale the microservices within an application. Health checks can also interact with Kubernetes liveness and readiness probes.
For example, in a microservices-based banking application, you might implement health checks on the login microservice, the balance transfer microservice, and the bill pay microservice. If a health check on the balance transfer microservice detects a bug or deadlock, it returns a DOWN
status. In this case, if the /health/live
endpoint is configured in a Kubernetes liveness probe, the probe restarts the microservice automatically. Restarting the microservice saves the user from encountering downtime or an error and preserves the functions of the other microservices in the application.
You can use MicroProfile Health with Open Liberty by enabling the MicroProfile Health feature in your server.xml
file.
MicroProfile Health endpoints and annotations
MicroProfile Health provides the following three endpoints:
-
/health/ready
This endpoint returns the readiness of a microservice, or whether it is ready to process requests. It corresponds to the Kubernetes readiness probe. -
/health/live
This endpoint returns the liveness of a microservice, or whether it encountered a bug or deadlock. If this check fails, the microservice is not running and can be stopped. This endpoint corresponds to the Kubernetes liveness probe, which automatically restarts the pod if the check fails. -
/health
This endpoint aggregates the responses from the/health/live
and/health/ready
endpoints. It corresponds to the deprecated@Health
annotation and is only available to provide compatibility with MicroProfile 1.0. If you are using MicroProfile 2.0 or higher, use the/health/ready
or/health/live
endpoints instead. The@Health
annotation is not available in MicroProfile 4.0 or later or MicroProfile Health 3.0 or later.
To add readiness or liveness health checks to your microservice, create a class in your application code that implements the HealthCheck interface and add either the @Liveness
or @Readiness
annotation to it. These annotations specify the conditions that determine whether the health check passes or fails.
You can view the results of the health checks by pointing your browser to one of the endpoint URLs, for example http://localhost:9443/health/live
or http://localhost:9443/health/ready
, where 9443
is the port number for your application. For more information, see Adding health reports to microservices.
The following example demonstrates the @Liveness
annotation in a class that implements the HealthCheck
interface. In this example, the @Liveness
annotation checks the heap memory usage. If heap memory usage is less than 90%, it returns an UP
status. If memory usage exceeds 90%, it returns a DOWN
status:
@Liveness
@ApplicationScoped
public class MemoryCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
long memUsed = memoryBean.getHeapMemoryUsage().getUsed();
long memMax = memoryBean.getHeapMemoryUsage().getMax();
HealthCheckResponse response = HealthCheckResponse.named("heap-memory")
.withData("used", memUsed)
.withData("max", memMax)
.status(memUsed < memMax * 0.9)
.build();
return response;
}
}
For MicroProfile Health versions 2.x and earlier, the .status
response is replaced by the .state
response in the HealthCheckResponse
class.
The following example shows the JSON response from the /health/live
endpoint if heap memory usage is less than 90%. The first status indicates the overall status of all health checks that are returned from the endpoint. An UP
status indicates that all the configured checks passed and that the service is available. A DOWN
status indicates that one or more checks failed and the service is unavailable. The second status indicates the status of the particular check that is specified by the preceding name
value, which in this example is heap-memory
. In this example, the liveness check passed and because it is the only check that is configured, the overall status is UP
:
{
"status": "UP",
"checks": [
{
"name": "heap-memory",
"status": "UP",
"data": {
"used": "1475462",
"max": ”51681681"
}
}
]
}
The next example shows the @Readiness
annotation on a class that implements the HealthCheck
interface. In this example, the @Readiness
annotation checks for a database connection. If the connection is successful, it returns an UP
status. If the connection is unsuccessful, it returns a DOWN
status:
@Readiness
@ApplicationScoped
public class DatabaseReadyCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
if (isDBConnected()) {
return HealthCheckResponse.up(“databaseReady”);
}
else {
return HealthCheckResponse.down(“databaseReady”);
}
}
}
The following example shows the JSON response from the /health/ready
endpoint if the database connection is unsuccessful. The first status indicates the overall status of all health checks that are returned from the endpoint. The second status indicates the status of the particular check that is specified by the preceding name
value, which in this example is databaseReady
. In this example, the readiness check failed and returned a DOWN
status so the overall status is also DOWN
:
{
"status": ”DOWN",
"checks": [
{
"name": ”databaseReady",
"status": ”DOWN",
}
]
}
In MicroProfile Health versions 2.0 and later, the overall default readiness status is DOWN
, with an empty response, until all the deployed applications in Open Liberty are started. In MicroProfile Health versions 3.0 and later, the mp.health.default.readiness.empty.response=UP
MicroProfile Config property is available. You can specify this property to change the overall default readiness status to UP
while deployed applications are starting up.