spring boot 2: actuator/health endpoint is taking more time

Viewed 2127

In one of my service /actuator/health endpoint is taking more time (approximately 9 seconds). I am using following dependencies, how to debug this?

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

Spring boot version used: 2.0.3.RELEASE

Thanks, Hari

3 Answers

Basically health endpoint is implemented in a way that it contains a list of all Spring beans that implement the interface HealthIndicator.

Each health indicator is responsible for supplying a health information about one subsystem (examples of such subsystem are:disk, postgres, mongo, etc.), spring boot comes with some predefined HealthIndicators.

So that when the health endpoint is invoked, it iterates through this list and gets the information about each subsystem and then constructs the answer.

Hence you can place a break point in relevant health indicators (assuming you know which subsystems are checked) and see what happens.

If you're looking for the HTTP entry point - the code that gets called when you call http://<host-port>/health (can vary depending on your settings but you get the idea)`, it can be found here

Yet another approach that comes to mind is disabling "suspicious" health check and finding the slow one by elimination.

For example, if you have an elastricsearch and would like to disable it, use in the application.properties:

management.health.elasticsearch.enabled = false

On top of Mark's answer, setting this property in your application.properties / application.yml

management.endpoint.health.show-details=always

Will help in identifying which components comprise the health check, as the GET /actuator/health will yield more details

On top of Mark's great answer:

As an alternative to synchronously running all your health checks when the /health endpoint is called (which can only lead to longer and longer execution time as you add more health checks), you can make your HealthIndicators run asynchronously using the library spring-boot-async-health-indicator (for Spring Boot >= 2.2) by annotating them with @AsyncHealth.

On top of making the /health endpoint return immediately (as returning healths calculated on separate threads), it also includes the execution time of each asynchronous health() method execution as an additional detail which dramatically helps in figuring out which underlying service responds slowly on production systems.

disclaimer: I wrote this library to help solve multiple limitations of the existing HealthIndicator system, including this one

Related