Contents

Overview

Microservices expose their health status primarily so external tools (for example, an orchestrator such as Kubernetes) can monitor each service and take action, such as restarting a service instance if it has failed or temporarily shunting traffic away from the instance if the service is unable to process the incoming requests normally.

Maven Coordinates

To enable MicroProfile Health add the helidon-microprofile bundle dependency to your project’s pom.xml (see Managing Dependencies).

<dependency>
    <groupId>io.helidon.microprofile.bundles</groupId>
    <artifactId>helidon-microprofile</artifactId>
</dependency>
Copied

MicroProfile Health is already included in the bundle.

If full control over the dependencies is required, and you want to minimize the quantity of the dependencies - Helidon MicroProfile Core budnle should be used. In this case the following dependencies should be included in your project’s pom.xml:

<dependency>
    <groupId>io.helidon.microprofile.bundles</groupId>
    <artifactId>helidon-microprofile-core</artifactId>
</dependency>
Copied
<dependency>
    <groupId>io.helidon.microprofile.health</groupId>
    <artifactId>helidon-microprofile-health</artifactId>
</dependency>
Copied

To enable built-in health checks add the following dependency (or use the helidon-microprofile bundle )

<dependency>
    <groupId>io.helidon.health</groupId>
    <artifactId>helidon-health-checks</artifactId>
</dependency>
Copied

Usage

Helidon implements MicroProfile Health Specification. The spec prescribes how external tools probe a service’s health checks and how you implement health checks as part of your microservice that are specific to your service’s needs.

Understanding Concepts

MicroProfile Health supports three types of health checks:

  • Liveness checks report whether the runtime environment in which the service is running is sufficient to support the work the service performs. The environment is beyond the control of the service itself and typically cannot improve without outside intervention. If a microservice instance reports a DOWN liveness check, it should never report UP later. It will need to be stopped and a replacement instance created.

  • Readiness checks report whether the service is currently capable of performing its work. A service that reports DOWN for its readiness cannot at the moment do its job, but at some future point it might become able to do so without requiring a restart.

  • Startup checks indicate whether the service has started to the point where liveness and readiness checks even make sense. A service reporting DOWN for a startup check is still initializing itself and normally will report UP soon, assuming it is able to start successfully.

REST Endpoints

A MicroProfile-compliant service reports its health via known REST endpoints. Helidon MP provides these endpoints automatically as part of every MP microservice that includes health support..

External management tools (or curl or browsers) retrieve health checks using the REST endpoints in the table below which summarizes the types of health checks in MicroProfile Health. Responses from the health endpoints report 200 (OK), 204 (no content), or 503 (service unavailable) depending on the outcome of running the health checks. HTTP GET responses include JSON content showing the detailed results of all the health checks which the server executed after receiving the request. HTTP HEAD requests return only the status with no payload.

Types of Health Checks
TypeMeaningREST endpointKubernetes response on failure
livenesswhether the runtime environment is suitable/health/liveRestarts container.
readinesswhether the microservice is currently capable of doing its work/health/readyDiverts requests away from the instance; periodically rechecks readiness and resumes traffic once the microservice reports itself as ready.
startupwhether the microservice has initialized to the point where liveness and readiness checks might pass/health/startedTreats the instance as still starting up; does not check liveness or readiness until the startup probe reports success or times out according to its configuration.

Configuration

Health checks may be configured using the following properties.

The class responsible for configuration is:

Type: io.helidon.health.HealthSupport

This is a standalone configuration type, prefix from configuration root: health

Configuration Options

Optional configuration options
keytypedefault valuedescription
cors 

Sets the cross-origin config builder for use in establishing CORS support for the service endpoints.

enabled

boolean

true

HealthSupport can be disabled by invoking this method.

exclude

string[]

 

Add health checks to a black list. Health check results that match by name with a blacklisted records will not be part of the result.

exclude-classes

Class<?>[]

 

A class may be excluded from invoking health checks on it. This allows configurable approach to disabling broken health-checks.

include

string[]

 

Add health checks to a white list (in case #includeAll is set to false.

routing

string

 

Sets the routing name to use for setting up the service’s endpoint.

timeout-millis

long

10000

health endpoint timeout (ms)

web-context

string

 

Sets the web context to use for the service’s endpoint.

Current properties may be set in application.yaml or in microprofile-config.properties with health prefix.

For example, you can specify a custom port and root context for the root health endpoint path. However, you cannot use different ports, such as http://localhost:8080/myhealth and http://localhost:8081/myhealth/live. Likewise, you cannot use different paths, such as http://localhost:8080/health and http://localhost:8080/probe/live. The example below will change the root path.

Create a file named microprofile-config.properties in the resources/META-INF directory with the following contents:
health.web-context=myhealth  
Copied
  • The web-context specifies a new root path for the health endpoint.

Examples

Generate Helidon MP Quickstart project following these Instruction

Using the Built-In Health Checks

Helidon has a set of built-in health checks that are enabled to report various health check statuses that are commonly used:

  • deadlock detection

  • available disk space

  • available heap memory

The following example will demonstrate how to use the built-in health checks. These examples are all executed from the root directory of your project (helidon-quickstart-mp).

Build the application, then run it:
mvn package
java -jar target/helidon-quickstart-mp.jar
Copied
Verify the health endpoint in a new terminal window:
curl http://localhost:8080/health
Copied
JSON response:
{
  "status": "UP",
  "checks": [
    {
      "name": "deadlock",
      "status": "UP"
    },
    {
      "name": "diskSpace",
      "status": "UP",
      "data": {
        "free": "325.54 GB",
        "freeBytes": 349543358464,
        "percentFree": "69.91%",
        "total": "465.63 GB",
        "totalBytes": 499963174912
      }
    },
    {
      "name": "heapMemory",
      "status": "UP",
      "data": {
        "free": "230.87 MB",
        "freeBytes": 242085696,
        "max": "3.56 GB",
        "maxBytes": 3817865216,
        "percentFree": "98.90%",
        "total": "271.00 MB",
        "totalBytes": 284164096
      }
    }
  ]
}
Copied

Custom Liveness Health Checks

You can create application-specific custom health checks and integrate them with Helidon using CDI. The following example shows how to add a custom liveness health check.

Create a new GreetLivenessCheck class with the following content:
@Liveness 
@ApplicationScoped 
public class GreetLivenessCheck implements HealthCheck {

  @Override
  public HealthCheckResponse call() {
    return HealthCheckResponse.named("LivenessCheck")  
        .up()
        .withData("time", System.currentTimeMillis())
        .build();
  }
}
Copied
  • Annotation indicating this is a liveness health check.
  • Annotation indicating this is a bean instantiated once per application (in Helidon this means just once per runtime).
  • Build the HealthCheckResponse with status UP and the current time.
Build and run the application, then verify the custom liveness health endpoint:
curl http://localhost:8080/health/live
Copied
JSON response:
{
  "status": "UP",
  "checks": [
    {
      "name": "LivenessCheck",
      "status": "UP",
      "data": {
        "time": 1566338255331
      }
    }
  ]
}
Copied

Full example code is available here.

Custom Readiness Health Checks

You can add a readiness check to indicate that the application is ready to be used. In this example, the server will wait five seconds before it becomes ready.

Create a new GreetReadinessCheck class with the following content:
@Readiness 
@ApplicationScoped
public class GreetReadinessCheck implements HealthCheck {
  private final AtomicLong readyTime = new AtomicLong(0);

  @Override
  public HealthCheckResponse call() {
    return HealthCheckResponse.named("ReadinessCheck")  
        .status(isReady())
        .withData("time", readyTime.get())
        .build();
  }

  public void onStartUp(
      @Observes @Initialized(ApplicationScoped.class) Object init) {
    readyTime.set(System.currentTimeMillis()); 
  }

  private boolean isReady() { 
    return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 5;
  }
}
Copied
  • Annotation indicating that this is a readiness health check.
  • Build the HealthCheckResponse with status UP after five seconds, else DOWN.
  • Record the time at startup.
  • Become ready after 5 seconds.
Build and run the application. Issue the curl command with -v within five seconds and you will see that the application is not ready:
curl -v  http://localhost:8080/health/ready
Copied
HTTP response status
< HTTP/1.1 503 Service Unavailable 
Copied
  • The HTTP status is 503 since the application is not ready.
JSON response body:
{
  "status": "DOWN",
  "checks": [
    {
      "name": "ReadinessCheck",
      "status": "DOWN",
      "data": {
        "time": 1566399775700
      }
    }
  ]
}
Copied
After five seconds you will see the application is ready:
curl -v http://localhost:8080/health/ready
Copied
HTTP response status
< HTTP/1.1 200 OK 
Copied
  • The HTTP status is 200 indicating that the application is ready.
JSON response body:
{
  "status": "UP",
  "checks": [
    {
      "name": "ReadinessCheck",
      "status": "UP",
      "data": {
        "time": 1566399775700
      }
    }
  ]
}
Copied

Full example code is available here.

Custom Startup Health Checks

You can add a startup check to indicate whether or not the application has initialized to the point that the other health checks make sense. In this example, the server will wait eight seconds before it declares itself started.

Create a new GreetStartedCheck class with the following content:
@Startup 
@ApplicationScoped
public class GreetStartedCheck implements HealthCheck {
  private final AtomicLong readyTime = new AtomicLong(0);


  @Override
  public HealthCheckResponse call() {
    return HealthCheckResponse.named("StartedCheck")  
        .status(isStarted())
        .withData("time", readyTime.get())
        .build();
  }

  public void onStartUp(
      @Observes @Initialized(ApplicationScoped.class) Object init) {
    readyTime.set(System.currentTimeMillis()); 
  }

  private boolean isStarted() { 
    return Duration.ofMillis(System.currentTimeMillis() - readyTime.get()).getSeconds() >= 8;
  }
}
Copied
  • Annotation indicating that this is a startup health check.
  • Build the HealthCheckResponse with status UP after eight seconds, else DOWN.
  • Record the time at startup of Helidon; the application will declare itself as started eight seconds later.
  • Become ready after 5 seconds.
Build and run the application. Issue the curl command with -v within five seconds and you will see that the application has not yet started:
curl -v  http://localhost:8080/health/started
Copied
HTTP response status:
< HTTP/1.1 503 Service Unavailable 
Copied
  • The HTTP status is 503 since the application has not started.
JSON response body:
{
  "status": "DOWN",
  "checks": [
    {
      "name": "StartedCheck",
      "status": "DOWN",
      "data": {
        "time": 1566399775700
      }
    }
  ]
}
Copied
After eight seconds you will see the application has started:
curl -v http://localhost:8080/health/started
Copied
HTTP response status:
< HTTP/1.1 200 OK 
Copied
  • The HTTP status is 200 indicating that the application is started.
JSON response body:
{
  "status": "UP",
  "checks": [
    {
      "name": "StartedCheck",
      "status": "UP",
      "data": {
        "time": 1566399775700
      }
    }
  ]
}
Copied

When using the health check URLs, you can get the following health check data:

Get all the health check data, including custom data:
curl http://localhost:8080/health
Copied
JSON response:
{
  "status": "UP",
  "checks": [
    {
      "name": "LivenessCheck",
      "status": "UP",
      "data": {
        "time": 1566403431536
      }
    }
  ]
}
Copied

Full example code is available here.

Reference