Skip to content

Commit 21f7b02

Browse files
authored
pattern: Implement Health Check for Microservices Observability (#2695) (#2774)
* Add Health Check pattern implementation The commit introduces Health Check pattern, providing a series of health indicators for system performance and stability monitoring, including checks for system CPU load, process CPU load, database health, memory usage, and garbage collection metrics. It also includes asynchronous execution and caching mechanisms for health checks, and retry configurations for resilience. Implements health checking components as per issue #2695. * Test cases and javadoc for HealthEndpointIntegrationTest * Added more log to test case to see why it returns 503 * Change config values to see if the system High system CPU load is resolved or not in CI. * Fixes for test cases. * some fixes for Sonar. * some fixes for Sonar. ADDED HIGH_PROCESS_CPU_LOAD_MESSAGE_WITHOUT_PARAM ADDED HIGH_SYSTEM_CPU_LOAD_MESSAGE_WITHOUT_PARAM * Sonar fixes address "Define and throw a dedicated exception instead of using a generic one." added HealthCheckInterruptedException refactored CustomHealthIndicator * fixes checkstyle violation.
1 parent 83dba61 commit 21f7b02

27 files changed

+2382
-0
lines changed

Diff for: health-check/README.md

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
title: Health Check Pattern
3+
category: Performance
4+
language: en
5+
tag:
6+
- Microservices
7+
- Resilience
8+
- Observability
9+
---
10+
11+
# Health Check Pattern
12+
13+
## Also known as
14+
Health Monitoring, Service Health Check
15+
16+
## Intent
17+
To ensure the stability and resilience of services in a microservices architecture by providing a way to monitor and diagnose their health.
18+
19+
## Explanation
20+
In microservices architecture, it's critical to continuously check the health of individual services. The Health Check Pattern is a mechanism for microservices to expose their health status. This pattern is implemented by including a health check endpoint in microservices that returns the service's current state. This is vital for maintaining system resilience and operational readiness.
21+
22+
## Class Diagram
23+
![alt text](./etc/health-check.png "Health Check")
24+
25+
## Applicability
26+
Use the Health Check Pattern when:
27+
- You have an application composed of multiple services and need to monitor the health of each service individually.
28+
- You want to implement automatic service recovery or replacement based on health status.
29+
- You are employing orchestration or automation tools that rely on health checks to manage service instances.
30+
31+
## Tutorials
32+
- Implementing Health Checks in Java using Spring Boot Actuator.
33+
34+
## Known Uses
35+
- Kubernetes Liveness and Readiness Probes
36+
- AWS Elastic Load Balancing Health Checks
37+
- Spring Boot Actuator
38+
39+
## Consequences
40+
**Pros:**
41+
- Enhances the fault tolerance of the system by detecting failures and enabling quick recovery.
42+
- Improves the visibility of system health for operational monitoring and alerting.
43+
44+
**Cons:**
45+
- Adds complexity to service implementation.
46+
- Requires a strategy to handle cascading failures when dependent services are unhealthy.
47+
48+
## Related Patterns
49+
- Circuit Breaker
50+
- Retry Pattern
51+
- Timeout Pattern
52+
53+
## Credits
54+
Inspired by the Health Check API pattern from [microservices.io](https://microservices.io/patterns/observability/health-check-api.html) and the issue [#2695](https://github.com/iluwatar/java-design-patterns/issues/2695) on iluwatar's Java design patterns repository.

Diff for: health-check/etc/health-check.png

159 KB
Loading

Diff for: health-check/etc/health-check.puml

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
@startuml
2+
3+
!theme plain
4+
top to bottom direction
5+
skinparam linetype ortho
6+
7+
class App {
8+
+ App():
9+
+ main(String[]): void
10+
}
11+
class AsynchronousHealthChecker {
12+
+ AsynchronousHealthChecker():
13+
+ performCheck(Supplier<Health>, long): CompletableFuture<Health>
14+
- awaitTerminationWithTimeout(): boolean
15+
+ shutdown(): void
16+
}
17+
class CpuHealthIndicator {
18+
+ CpuHealthIndicator():
19+
- processCpuLoadThreshold: double
20+
- systemCpuLoadThreshold: double
21+
- loadAverageThreshold: double
22+
- osBean: OperatingSystemMXBean
23+
- defaultWarningMessage: String
24+
+ init(): void
25+
+ health(): Health
26+
defaultWarningMessage: String
27+
osBean: OperatingSystemMXBean
28+
loadAverageThreshold: double
29+
processCpuLoadThreshold: double
30+
systemCpuLoadThreshold: double
31+
}
32+
class CustomHealthIndicator {
33+
+ CustomHealthIndicator(AsynchronousHealthChecker, CacheManager, HealthCheckRepository):
34+
+ evictHealthCache(): void
35+
- check(): Health
36+
+ health(): Health
37+
}
38+
class DatabaseTransactionHealthIndicator {
39+
+ DatabaseTransactionHealthIndicator(HealthCheckRepository, AsynchronousHealthChecker, RetryTemplate):
40+
- retryTemplate: RetryTemplate
41+
- healthCheckRepository: HealthCheckRepository
42+
- timeoutInSeconds: long
43+
- asynchronousHealthChecker: AsynchronousHealthChecker
44+
+ health(): Health
45+
timeoutInSeconds: long
46+
retryTemplate: RetryTemplate
47+
healthCheckRepository: HealthCheckRepository
48+
asynchronousHealthChecker: AsynchronousHealthChecker
49+
}
50+
class GarbageCollectionHealthIndicator {
51+
+ GarbageCollectionHealthIndicator():
52+
- memoryUsageThreshold: double
53+
+ health(): Health
54+
memoryPoolMxBeans: List<MemoryPoolMXBean>
55+
garbageCollectorMxBeans: List<GarbageCollectorMXBean>
56+
memoryUsageThreshold: double
57+
}
58+
class HealthCheck {
59+
+ HealthCheck():
60+
- status: String
61+
- id: Integer
62+
+ equals(Object): boolean
63+
# canEqual(Object): boolean
64+
+ hashCode(): int
65+
+ toString(): String
66+
id: Integer
67+
status: String
68+
}
69+
class HealthCheckRepository {
70+
+ HealthCheckRepository():
71+
+ performTestTransaction(): void
72+
+ checkHealth(): Integer
73+
}
74+
class MemoryHealthIndicator {
75+
+ MemoryHealthIndicator(AsynchronousHealthChecker):
76+
+ checkMemory(): Health
77+
+ health(): Health
78+
}
79+
class RetryConfig {
80+
+ RetryConfig():
81+
+ retryTemplate(): RetryTemplate
82+
}
83+
84+
CustomHealthIndicator "1" *-[#595959,plain]-> "healthChecker\n1" AsynchronousHealthChecker
85+
CustomHealthIndicator "1" *-[#595959,plain]-> "healthCheckRepository\n1" HealthCheckRepository
86+
DatabaseTransactionHealthIndicator "1" *-[#595959,plain]-> "asynchronousHealthChecker\n1" AsynchronousHealthChecker
87+
DatabaseTransactionHealthIndicator "1" *-[#595959,plain]-> "healthCheckRepository\n1" HealthCheckRepository
88+
HealthCheckRepository -[#595959,dashed]-> HealthCheck : "«create»"
89+
MemoryHealthIndicator "1" *-[#595959,plain]-> "asynchronousHealthChecker\n1" AsynchronousHealthChecker
90+
@enduml

Diff for: health-check/pom.xml

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
This project is licensed under the MIT license. Module model-view-viewmodel is using ZK framework licensed under LGPL (see lgpl-3.0.txt).
5+
6+
The MIT License
7+
Copyright © 2014-2022 Ilkka Seppälä
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in
17+
all copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
THE SOFTWARE.
26+
27+
-->
28+
<project xmlns="http://maven.apache.org/POM/4.0.0"
29+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
30+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
31+
<modelVersion>4.0.0</modelVersion>
32+
<parent>
33+
<groupId>com.iluwatar</groupId>
34+
<artifactId>java-design-patterns</artifactId>
35+
<version>1.26.0-SNAPSHOT</version>
36+
</parent>
37+
38+
<artifactId>health-check</artifactId>
39+
40+
<dependencies>
41+
<!-- Spring Boot Dependencies -->
42+
<dependency>
43+
<groupId>org.springframework.boot</groupId>
44+
<artifactId>spring-boot-starter-web</artifactId>
45+
</dependency>
46+
47+
<!-- Spring Boot Actuator for health check -->
48+
<dependency>
49+
<groupId>org.springframework.boot</groupId>
50+
<artifactId>spring-boot-starter-actuator</artifactId>
51+
</dependency>
52+
53+
<!-- Spring Boot Data JPA for database access -->
54+
<dependency>
55+
<groupId>org.springframework.boot</groupId>
56+
<artifactId>spring-boot-starter-data-jpa</artifactId>
57+
</dependency>
58+
59+
<!-- Testing Dependencies -->
60+
<dependency>
61+
<groupId>org.springframework.boot</groupId>
62+
<artifactId>spring-boot-starter-test</artifactId>
63+
<scope>test</scope>
64+
</dependency>
65+
66+
<!-- Spring Retry for retrying failed database operations -->
67+
<dependency>
68+
<groupId>org.springframework.retry</groupId>
69+
<artifactId>spring-retry</artifactId>
70+
</dependency>
71+
72+
73+
<!-- JUnit Jupiter Engine for testing -->
74+
<dependency>
75+
<groupId>org.junit.jupiter</groupId>
76+
<artifactId>junit-jupiter-engine</artifactId>
77+
<scope>test</scope>
78+
</dependency>
79+
80+
<!-- Mockito for mocking in tests -->
81+
<dependency>
82+
<groupId>org.mockito</groupId>
83+
<artifactId>mockito-core</artifactId>
84+
<scope>test</scope>
85+
</dependency>
86+
87+
<!-- H2 for mocking database -->
88+
<dependency>
89+
<groupId>com.h2database</groupId>
90+
<artifactId>h2</artifactId>
91+
<scope>runtime</scope>
92+
</dependency>
93+
94+
<!-- https://mvnrepository.com/artifact/org.assertj/assertj-core -->
95+
<dependency>
96+
<groupId>org.assertj</groupId>
97+
<artifactId>assertj-core</artifactId>
98+
<version>3.24.2</version>
99+
<scope>test</scope>
100+
</dependency>
101+
102+
<dependency>
103+
<groupId>io.rest-assured</groupId>
104+
<artifactId>rest-assured</artifactId>
105+
<scope>test</scope>
106+
</dependency>
107+
108+
109+
</dependencies>
110+
111+
112+
<build>
113+
<plugins>
114+
<!-- Maven Assembly Plugin for creating a single distributable JAR -->
115+
<plugin>
116+
<groupId>org.apache.maven.plugins</groupId>
117+
<artifactId>maven-assembly-plugin</artifactId>
118+
<executions>
119+
<execution>
120+
<phase>package</phase>
121+
<goals>
122+
<goal>single</goal>
123+
</goals>
124+
<configuration>
125+
<descriptorRefs>
126+
<descriptorRef>jar-with-dependencies</descriptorRef>
127+
</descriptorRefs>
128+
<archive>
129+
<manifest>
130+
<!-- Define the main class for the executable JAR -->
131+
<mainClass>com.iluwatar.healthcheck.App</mainClass>
132+
</manifest>
133+
</archive>
134+
</configuration>
135+
</execution>
136+
</executions>
137+
</plugin>
138+
139+
<!-- Other plugins as needed -->
140+
141+
</plugins>
142+
</build>
143+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.iluwatar.health.check;
2+
3+
import org.springframework.boot.SpringApplication;
4+
import org.springframework.boot.autoconfigure.SpringBootApplication;
5+
import org.springframework.cache.annotation.EnableCaching;
6+
import org.springframework.scheduling.annotation.EnableScheduling;
7+
8+
/**
9+
* This application provides health check APIs for various aspects of the microservice architecture,
10+
* including database transactions, garbage collection, and overall system health. These health
11+
* checks are essential for monitoring the health and performance of the microservices and ensuring
12+
* their availability and responsiveness. For more information about health checks and their role in
13+
* microservice architectures, please refer to: [Microservices Health Checks
14+
* API]('https://microservices.io/patterns/observability/health-check-api.html').
15+
*
16+
* @author ydoksanbir
17+
*/
18+
@EnableCaching
19+
@EnableScheduling
20+
@SpringBootApplication
21+
public class App {
22+
/** Program entry point. */
23+
public static void main(String[] args) {
24+
SpringApplication.run(App.class, args);
25+
}
26+
}

0 commit comments

Comments
 (0)