In the world of microservices, where applications are decomposed into smaller, independent services, maintaining visibility into the health of each service is crucial. Spring Boot provides a powerful combination of the Spring Discovery Client and Actuator to simplify this task. In this blog post, we’ll walk through building a Spring service that leverages these tools to monitor the health status of your microservices.

Building the Health Status Service

Let’s dive into the code for the HealthStatusService:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class HealthStatusService {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;

    public Map<String, Map<String, String>> getHealthStatus() {
        Map<String, Map<String, String>> result = new HashMap<>();

        List<String> services = discoveryClient.getServices();
        for (String serviceId : services) {
            List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
            for (ServiceInstance instance : instances) {
                String url = instance.getUri().toString() + "/actuator/health";
                ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);

                String status = (response.getStatusCode() == HttpStatus.OK) ? "UP" : "DOWN";

                Map<String, String> instanceStatus = new HashMap<>();
                instanceStatus.put(instance.getInstanceId(), status);

                result.computeIfAbsent(serviceId, k -> new HashMap<>()).putAll(instanceStatus);
            }
        }

        return result;
    }
}

Project Setup

Gradle:

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client' 
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

Maven:

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

application.yml:

spring:
  application:
    name: health-monitor-service 

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/ 

management:
  endpoints:
    web:
      exposure:
        include: health 

Considerations

  • Security: Exposing the Actuator endpoints, especially /health, can have security implications. Consider using Spring Security to protect these endpoints.
  • Error Handling: Implement more robust error handling to gracefully manage scenarios like network failures or service unavailability.
  • Caching: Introduce caching to reduce the frequency of health checks and improve performance.
  • Custom Health Checks: Explore the possibility of adding custom health checks to your microservices to provide more detailed health information.
  • Monitoring and Alerting: Integrate your health monitoring service with a monitoring and alerting system to proactively identify and respond to issues.

Monitoring the health of your microservices is essential for maintaining a resilient and reliable system. The Spring Discovery Client and Actuator offer a straightforward way to achieve this. By building a dedicated health monitoring service, you can gain valuable insights into the health of your microservices ecosystem.


Discover more from GhostProgrammer - Jeff Miller

Subscribe to get the latest posts sent to your email.

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.