Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/openliberty/guide-microprofile-health
A guide on how to report and check the health of a microservice with MicroProfile Health: https://openliberty.io/guides/microprofile-health.html
https://github.com/openliberty/guide-microprofile-health
Last synced: 3 months ago
JSON representation
A guide on how to report and check the health of a microservice with MicroProfile Health: https://openliberty.io/guides/microprofile-health.html
- Host: GitHub
- URL: https://github.com/openliberty/guide-microprofile-health
- Owner: OpenLiberty
- License: other
- Created: 2018-01-15T19:41:45.000Z (about 7 years ago)
- Default Branch: prod
- Last Pushed: 2024-09-04T20:20:33.000Z (5 months ago)
- Last Synced: 2024-09-07T00:56:36.096Z (5 months ago)
- Language: Java
- Homepage:
- Size: 1.01 MB
- Stars: 4
- Watchers: 6
- Forks: 14
- Open Issues: 2
-
Metadata Files:
- Readme: README.adoc
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
// Copyright (c) 2018, 2023 IBM Corporation and others.
// Licensed under Creative Commons Attribution-NoDerivatives
// 4.0 International (CC BY-ND 4.0)
// https://creativecommons.org/licenses/by-nd/4.0/
//
// Contributors:
// IBM Corporation
:projectid: microprofile-health
:page-layout: guide-multipane
:page-duration: 20 minutes
:page-releasedate: 2018-03-15
:page-guide-category: microprofile
:page-essential: false
:page-description: Learn how to use MicroProfile Health to provide and check the health of a microservice.
:page-tags: ['MicroProfile']
:page-permalink: /guides/{projectid}
:page-related-guides: ['microprofile-config', 'microprofile-metrics', 'cdi-intro', 'rest-intro']
:common-includes: https://raw.githubusercontent.com/OpenLiberty/guides-common/prod
:source-highlighter: prettify
:page-seo-title: Checking the health of Java microservices by using Eclipse MicroProfile Health Check
:page-seo-description: A getting started tutorial and an example on how to monitor and report the health status of Java microservices by implementing readiness and liveness checks using Eclipse MicroProfile Health.
:guide-author: Open Liberty
= Adding health reports to microservices[.hidden]
NOTE: This repository contains the guide documentation source. To view the guide in published form, view it on the https://openliberty.io/guides/{projectid}.html[Open Liberty website].Explore how to report and check the health of a microservice with MicroProfile Health.
// =================================================================================================
// What you'll learn
// =================================================================================================== What you'll learn
You will learn how to use MicroProfile Health to report the health status of microservices and take appropriate actions based on this report.
MicroProfile Health allows services to report their health, and it publishes the overall health status to a defined endpoint. A service reports `UP` if it is available and reports `DOWN` if it is unavailable. MicroProfile Health reports an individual service status at the endpoint and indicates the overall status as `UP` if all the services are `UP`. A service orchestrator can then use the health statuses to make decisions.
A service checks its own health by performing necessary self-checks and then reports its overall status by implementing the API provided by MicroProfile Health. A self-check can be a check on anything that the service needs, such as a dependency, a successful connection to an endpoint, a system property, a database connection, or the availability of required resources. MicroProfile offers checks for startup, liveness, and readiness.
You will add startup, liveness, and readiness checks to the `system` and `inventory` services, that are provided for you, and implement what is necessary to report health status by using MicroProfile Health.
// =================================================================================================
// Getting Started
// =================================================================================================[role='command']
include::{common-includes}/gitclone.adoc[]// =================================================================================================
// Try what you'll build
// =================================================================================================[role='command']
include::{common-includes}/twyb-intro.adoc[]// static guide instructions:
ifndef::cloud-hosted[]
The `system` and `inventory` services can be found at the following URLs:* http://localhost:9080/system/properties[http://localhost:9080/system/properties^]
* http://localhost:9080/inventory/systems[http://localhost:9080/inventory/systems^]
Visit the http://localhost:9080/health[http://localhost:9080/health^] URL to see the overall health status of the application, as well as the aggregated data of the startup, liveness and readiness checks. Three checks show the state of the `system` service, and the other three checks show the state of the `inventory` service. As you might expect, all services are in the `UP` state, and the overall health status of the application is in the `UP` state.
Access the `/health/started` endpoint by visiting the http://localhost:9080/health/started[http://localhost:9080/health/started^] URL to view the data from the startup health checks. You can also access the `/health/live` endpoint by visiting the http://localhost:9080/health/live[http://localhost:9080/health/live^] URL to view the data from the liveness health checks. Similarly, access the `/health/ready` endpoint by visiting the http://localhost:9080/health/ready[http://localhost:9080/health/ready^] URL to view the data from the readiness health checks.
endif::[]// cloud-hosted guide instructions:
ifdef::cloud-hosted[]
Open another command-line session by selecting **Terminal** > **New Terminal** from the menu of the IDE. To access the **system** service, run the following curl command:
```bash
curl -s http://localhost:9080/system/properties | jq
```To access the ***inventory*** service, run the following curl command:
```bash
curl -s http://localhost:9080/inventory/systems | jq
```Visit the http://localhost:9080/health URL to see the overall health status of the application, as well as the aggregated data of the startup, liveness, and readiness checks. Run the following curl command:
```bash
curl -s http://localhost:9080/health | jq
```Three checks show the state of the ***system*** service, and the other three checks show the state of the ***inventory*** service. As you might expect, all services are in the **UP** state, and the overall health status of the application is in the ***UP*** state.
Access the ***/health/started*** endpoint by visiting the http://localhost:9080/health/started URL to view the data from the startup health checks. Run the following curl command:
```bash
curl -s http://localhost:9080/health/started | jq
```You can also access the ***/health/live*** endpoint by visiting the http://localhost:9080/health/live URL to view the data from the liveness health checks. Run the following curl command:
```bash
curl -s http://localhost:9080/health/live | jq
```Similarly, access the ***/health/ready*** endpoint by visiting the http://localhost:9080/health/ready URL to view the data from the readiness health checks. Run the following curl command:
```bash
curl -s http://localhost:9080/health/ready | jq
```
endif::[][role='command']
include::{common-includes}/twyb-end.adoc[]// =================================================================================================
// Adding health checks to microservices
// =================================================================================================== Adding health checks to microservices
// static guide instructions:
ifndef::cloud-hosted[]
Navigate to the `start` directory to begin.
endif::[]// cloud-hosted guide instructions:
ifdef::cloud-hosted[]
To begin, run the following command to navigate to the ***start*** directory:
```bash
cd /home/project/guide-microprofile-health/start
```
endif::[][role='command']
include::{common-includes}/devmode-lmp33-start.adoc[]A health report will be generated automatically for all services that enable MicroProfile Health. The [hotspot=mpHealth]`mpHealth` feature has already been enabled for you in the [hotspot]`src/main/liberty/config/server.xml` file.
All services must provide an implementation of the `HealthCheck` interface, which is used to verify their health. MicroProfile Health offers health checks for startup, liveness, and readiness. A startup check allows applications to define startup probes that are used for initial verification of the application before the Liveness probe takes over. For example, a startup check might check which applications require additional startup time on their first initialization. A liveness check allows third-party services to determine whether a microservice is running. If the liveness check fails, the application can be terminated. For example, a liveness check might fail if the application runs out of memory. A readiness check allows third-party services, such as Kubernetes, to determine whether a microservice is ready to process requests. For example, a readiness check might check dependencies, such as database connections.
server.xml
[source, xml, linenums, role='code_column']
----
include::finish/src/main/liberty/config/server.xml[]
----// =================================================================================================
// Adding health checks to the system service
// ==================================================================================================== Adding health checks to the system service
[role="code_command hotspot file=0", subs="quotes"]
----
#Create the `SystemStartupCheck` class.#
`src/main/java/io/openliberty/guides/system/SystemStartupCheck.java`
----SystemStartupCheck.java
[source, java, linenums, role='code_column tags=SystemStartupCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/system/SystemStartupCheck.java[]
----The [hotspot=Startup file=0]`@Startup` annotation indicates that this class is a startup health check procedure. In this case, you are checking the cpu usage. If more than 95% of the cpu is being used, a status of `DOWN` is returned.
[role="code_command hotspot file=1", subs="quotes"]
----
#Create the `SystemLivenessCheck` class.#
`src/main/java/io/openliberty/guides/system/SystemLivenessCheck.java`
----SystemLivenessCheck.java
[source, java, linenums, role='code_column tags=SystemLivenessCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/system/SystemLivenessCheck.java[]
----The [hotspot=Liveness file=1]`@Liveness` annotation indicates that this class is a liveness health check procedure. In this case, you are checking the heap memory usage. If more than 90% of the maximum memory is being used, a status of `DOWN` is returned.
[role="code_command hotspot file=2", subs="quotes"]
----
#Create the `SystemReadinessCheck` class.#
`src/main/java/io/openliberty/guides/system/SystemReadinessCheck.java`
----SystemReadinessCheck.java
[source, java, linenums, role='code_column tags=SystemReadinessCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/system/SystemReadinessCheck.java[]
----// static guide instructions:
ifndef::cloud-hosted[]
The [hotspot=Readiness file=2]`@Readiness` annotation indicates that this class is a readiness health check procedure. By pairing this annotation with the [hotspot=ApplicationScoped file=2]`ApplicationScoped` context from the Contexts and Dependency Injections API, the bean is discovered automatically when the `\http://localhost:9080/health` endpoint receives a request.
endif::[]// cloud-hosted guide instructions:
ifdef::cloud-hosted[]
The ***@Readiness*** annotation indicates that this class is a readiness health check procedure. By pairing this annotation with the ***ApplicationScoped*** context from the Contexts and Dependency Injections API, the bean is discovered automatically when the http://localhost:9080/health endpoint receives a request.
endif::[]The [hotspot=healthCheckResponse file=2]`call()` method is used to return the health status of a particular service. In this case, you are checking if the server name is [hotspot=defaultServer file=2]`defaultServer` and returning [hotspot=HealthCheckResponse-UP file=2]`UP` if it is, and [hotspot=HealthCheckResponse-DOWN file=2]`DOWN` otherwise. This example is a very simple implementation of the [hotspot=healthCheckResponse file=2]`call()` method. In a real environment, you would orchestrate more meaningful health checks.
// =================================================================================================
// Adding health checks to the inventory service
// ==================================================================================================== Adding health checks to the inventory service
[role="code_command hotspot file=0", subs="quotes"]
----
#Create the `InventoryStartupCheck` class.#
`src/main/java/io/openliberty/guides/inventory/InventoryStartupCheck.java`
----InventoryStartupCheck.java
[source, java, linenums, role='code_column tags=InventoryStartupCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/inventory/InventoryStartupCheck.java[]
----This startup check verifies that the cpu usage is below 95%.
If more than 95% of the cpu is being used, a status of `DOWN` is returned.[role="code_command hotspot file=1", subs="quotes"]
----
#Create the `InventoryLivenessCheck` class.#
`src/main/java/io/openliberty/guides/inventory/InventoryLivenessCheck.java`
----InventoryLivenessCheck.java
[source, java, linenums, role='code_column tags=InventoryLivenessCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/inventory/InventoryLivenessCheck.java[]
----As with the `system` liveness check, you are checking the heap memory usage. If more than 90% of the maximum memory is being used, a `DOWN` status is returned.
[role="code_command hotspot file=2", subs="quotes"]
----
#Create the `InventoryReadinessCheck` class.#
`src/main/java/io/openliberty/guides/inventory/InventoryReadinessCheck.java`
----InventoryReadinessCheck.java
[source, java, linenums, role='code_column tags=InventoryReadinessCheck hide_tags=copyright']
----
include::finish/src/main/java/io/openliberty/guides/inventory/InventoryReadinessCheck.java[]
----In the [hotspot=isHealthy file=2]`isHealthy()` method, you report the `inventory` service as not ready if the service is in maintenance or if its dependant service is unavailable.
For simplicity, the custom [hotspot=3 file=3]`io_openliberty_guides_inventory_inMaintenance` MicroProfile Config property, which is defined in the [hotspot file=3]`resources/CustomConfigSource.json` file, indicates whether the service is in maintenance. This file was already created for you.
Moreover, the readiness health check procedure makes an HTTP [hotspot=getRequest file=2]`GET` request to the `system` service and checks its status. If the request is successful, the `inventory` service is healthy and ready because its dependant service is available. Otherwise, the `inventory` service is not ready and an unhealthy readiness status is returned.
If you are curious about the injected [hotspot=inventoryConfig file=2]`inventoryConfig` object or if you want to learn more about MicroProfile Config, see https://openliberty.io/guides/microprofile-config.html[Configuring microservices^].
CustomConfigSource.json
[source, json, linenums, role='code_column']
----
include::finish/resources/CustomConfigSource.json[]
----// =================================================================================================
// Building and running the application
// =================================================================================================[role='command']
include::{common-includes}/devmode-build.adoc[]// static guide instructions:
ifndef::cloud-hosted[]
While the Liberty is running, navigate to the http://localhost:9080/health[http://localhost:9080/health^] URL to find the aggregated startup, liveness, and readiness health reports on the two services.You can also navigate to the http://localhost:9080/health/started[http://localhost:9080/health/started^] URL to view the startup health report, to the http://localhost:9080/health/live[http://localhost:9080/health/live^] URL to view the liveness health report or the http://localhost:9080/health/ready[http://localhost:9080/health/ready^] URL to view the readiness health report.
Put the `inventory` service in maintenance by setting the [hotspot=3]`io_openliberty_guides_inventory_inMaintenance` property to `true` in the [hotspot]`CustomConfigSource.json` file.
[role="code_command hotspot file=0", subs="quotes"]
----
#Replace the `CustomConfigSource.json` file.#
`resources/CustomConfigSource.json`
----
CustomConfigSource.json
[source, json, linenums, role='code_column']
----
include::finish/resources/CustomConfigSource2.json[]
----Because this configuration file is picked up dynamically, simply refresh the http://localhost:9080/health[http://localhost:9080/health^] URL to see that the state of the `inventory` service changed to `DOWN`. The overall state of the application also changed to `DOWN` as a result. Go to the http://localhost:9080/inventory/systems[http://localhost:9080/inventory/systems^] URL to verify that the `inventory` service is indeed in maintenance. Set the [hotspot=3]`io_openliberty_guides_inventory_inMaintenance` property back to `false` after you are done.
endif::[]// cloud-hosted guide instructions:
ifdef::cloud-hosted[]
While the Liberty is running, run the following curl command to find the aggregated startup ,liveness, and readiness health reports on the two services:
```bash
curl -s http://localhost:9080/health | jq
```You can also run the following curl command to view the startup health report:
```bash
curl -s http://localhost:9080/health/started | jq
```or run the following curl command to view the liveness health report:
```bash
curl -s http://localhost:9080/health/live | jq
```or run the following curl command to view the readiness health report:
```bash
curl -s http://localhost:9080/health/ready | jq
```Put the ***inventory*** service in maintenance by setting the ***io_openliberty_guides_inventory_inMaintenance*** property to ***true*** in the ***resources/CustomConfigSource.json*** file.
> From the menu of the IDE, select
**File** > **Open** > guide-microprofile-health/start/resources/CustomConfigSource.json, or click the following button::openFile{path="/home/project/guide-microprofile-health/start/resources/CustomConfigSource.json"}
```text
{
"config_ordinal":700,
"io_openliberty_guides_inventory_inMaintenance":true
}
```Because this configuration file is picked up dynamically, simply refresh the http://localhost:9080/health URL to see that the state of the **inventory** service changed to ***DOWN***. Run the following curl command:
```bash
curl -s http://localhost:9080/health | jq
```The overall state of the application also changed to ***DOWN*** as a result. Run the following curl command to verify that the **inventory** service is indeed in maintenance:
```bash
curl -s http://localhost:9080/inventory/systems | jq
```Set the ***io_openliberty_guides_inventory_inMaintenance*** property back to **false** after you are done.
> From the menu of the IDE, select
**File** > **Open** > guide-microprofile-health/start/resources/CustomConfigSource.json, or click the following button::openFile{path="/home/project/guide-microprofile-health/start/resources/CustomConfigSource.json"}
```text
{
"config_ordinal":700,
"io_openliberty_guides_system_inMaintenance":false
}
```endif::[]
// =================================================================================================
// Testing health checks
// =================================================================================================== Testing health checks
You will implement several test methods to validate the health of the `system` and `inventory` services.
[role="code_command hotspot file=0", subs="quotes"]
----
#Create the `HealthIT` class.#
`src/test/java/it/io/openliberty/guides/health/HealthIT.java`
----HealthIT.java
[source, java, linenums, role='code_column tags=HealthIT hide_tags=copyright']
----
include::finish/src/test/java/it/io/openliberty/guides/health/HealthIT.java[]
----Let's break down the test cases:
* The [hotspot=testStartup file=0]`testStartup()` test case compares the generated health report for the startup checks with the actual status of the services.
* The [hotspot=testLiveness file=0]`testLiveness()` test case compares the generated health report for the liveness checks with the actual status of the services.
* The [hotspot=testReadiness file=0]`testReadiness()` test case compares the generated health report for the readiness checks with the actual status of the services.
* The [hotspot=testHealth file=0]`testHealth()` test case compares the generated health report with the actual status of the services. This test also puts the `inventory` service in maintenance by setting the [hotspot=3 file=1]`io_openliberty_guides_inventory_inMaintenance` property to `true` and comparing the generated health report with the actual status of the services.A few more tests were included to verify the basic functionality of the `system` and `inventory` services. They can be found under the [hotspot file=2]`src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java` and [hotspot file=3]`src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java` files. If a test failure occurs, then you might have introduced a bug into the code. These tests run automatically as a part of the integration test suite.
CustomConfigSource.json
[source, json, linenums, role='code_column']
----
include::finish/resources/CustomConfigSource.json[]
----InventoryEndpointIT.java
[source, Java, linenums, role='code_column hide_tags=copyright']
----
include::finish/src/test/java/it/io/openliberty/guides/inventory/InventoryEndpointIT.java[]
----SystemEndpointIT.java
[source, Java, linenums, role='code_column hide_tags=copyright']
----
include::finish/src/test/java/it/io/openliberty/guides/system/SystemEndpointIT.java[]
----// =================================================================================================
// Running the tests
// =================================================================================================[role='command']
include::{common-includes}/devmode-test.adoc[]You see the following output:
[source, role="no_copy"]
----
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running it.io.openliberty.guides.health.HealthIT
[INFO] [WARNING ] CWMMH0052W: The class io.openliberty.microprofile.health30.impl.HealthCheck30ResponseImpl implementing HealthCheckResponse in the guide-microprofile-health application in module guide-microprofile-health.war, reported a DOWN status with data Optional[{}].
[INFO] Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.706 s - in it.io.openliberty.guides.health.HealthIT
[INFO] Running it.io.openliberty.guides.system.SystemEndpointIT
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0 s - in it.io.openliberty.guides.system.SystemEndpointIT
[INFO] Running it.io.openliberty.guides.inventory.InventoryEndpointIT
[INFO] [WARNING ] Interceptor for {http://client.inventory.guides.openliberty.io/}SystemClient has thrown exception, unwinding now
[INFO] Could not send Message.
[INFO] [err] The specified host is unknown.
[INFO] Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.171 s - in it.io.openliberty.guides.inventory.InventoryEndpointIT
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 8, Failures: 0, Errors: 0, Skipped: 0
----The warning messages are expected. The first warning results from a request to a service that is under maintenance. This request is made in the `testHealth()` test from the `InventoryEndpointIT` integration test. The second warning and error results from a request to a bad or an unknown hostname. This request is made in the `testUnknownHost()` test from the `InventoryEndpointIT` integration test.
The tests might fail if your system CPU or memory use is high. The status of the system is DOWN if the CPU usage is over 95%, or the memory usage is over 90%.
To see whether the tests detect a failure, manually change the configuration of [hotspot=3 file=1]`io_openliberty_guides_inventory_inMaintenance` from `false` to `true` in the `resources/CustomConfigSource.json` file. Rerun the tests to see a test failure occur. The test failure occurs because the initial status of the `inventory` service is `DOWN`.
[role='command']
include::{common-includes}/devmode-quit-ctrlc.adoc[]// =================================================================================================
// Great work! You're done!
// =================================================================================================== Great work! You're done!
You just learned how to add health checks to report the states of microservices by using MicroProfile Health in Open Liberty. Then, you wrote tests to validate the generated health report.
Feel free to try one of the related MicroProfile guides. They demonstrate additional technologies that you can learn and expand on top of what you built here.
include::{common-includes}/attribution.adoc[subs="attributes"]