How to create a custom Health Check in Spring Boot for Microservices?

Let’s say you have three microservices in your application.

One of the microservices connects to the other two microservices.

And in addition it also connects to a database.

You want to check the health status of this microservice and its dependent microservices and database.

How to do this in Spring Boot?

Spring Boot provides an inbuilt health check service to check the connectivity of your application.

You just need to add “spring-boot-starter-actuator” dependency and the health check becomes automatically available at /actuator/health endpoint.

But how do you check the health status of the dependent microservices and database?

To check the connection to the database , you need to enable a property in application.yml and Spring will automatically check it and add it to the response provided by /actuator/health endpoint.

But to check the connectivity to the other microservices you need to create a custom health check.

Here are the overall steps to be followed:

STEP1: Add Spring Boot Actuator dependency

	<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>

Once this is done , the /actuator/health endpoint gets activated:

It shows that the application is up.

STEP2: Enable “show-details” flag in application.yml file

To find out if database is up and to add custom health checks the following property needs to be enabled in application.yml:

management:
  endpoint:
    health:
      show-details: always

Now Spring will show additional details like disk storage.

Also if you have any database configured through your application yml file , Spring will check its connectivity too:

STEP3: Enable health checks in all the dependent microservices

To check the health check of dependent microservices ,enable their health check endpoints as done for the current microservice in Step 1.

By doing so the /actuator/health endpoint gets enabled for each of those microservices.

Here is the health check of one of the microservices I deployed in a different port:

STEP4: Create a custom health check for each dependent microservice

For each microservice create a custom health check by extending HealthIndicator interface.

And then override the health() method.

Inside the health() method hit the actuator endpoint of the dependent microservice (/actuator/health).

If the response is successful return a “UP” health object else “DOWN” health object as shown below:

package com.example.msdoc;

import java.util.Map;

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class Microservice1HealthCheck implements HealthIndicator {

	@Override
	public Health health() {

		RestTemplate restTemplate = new RestTemplate();
		ResponseEntity<Map> response = restTemplate.getForEntity("http://localhost:8081/actuator/health", Map.class);
		Map<String, Object> respMap = response.getBody();

		String status = (String) respMap.get("status");

		if (status.equals("UP")) {

			return Health.up().build();
		}

		return Health.down().build();

	}

}

Create such a custom health check class for each microservice.

STEP5: Test

Test your /actuator/health endpoint.

Here is the response I got for the example discussed so far:

{
    "status": "UP",
    "components": {
        "db": {
            "status": "UP",
            "details": {
                "database": "H2",
                "validationQuery": "isValid()"
            }
        },
        "diskSpace": {
            "status": "UP",
            "details": {
                "total": 481242902528,
                "free": 384073994240,
                "threshold": 10485760,
                "exists": true
            }
        },
        "microservice1HealthCheck": {
            "status": "UP"
        },
        "microservice2HealthCheck": {
            "status": "UP"
        },
        "ping": {
            "status": "UP"
        }
    }
}

As you see there are two new objects “microservice1HealthCheck” and “microservice2HealthCheck” each returning the status of the respective microservices.

In this way you can get the health status of your microservice and all its dependent services.

That’s it!

Code here:

https://github.com/vijaysrj/customhealthcheck

Comments

Leave a Reply

Discover more from The Full Stack Developer

Subscribe now to keep reading and get access to the full archive.

Continue reading