grpc-ecosystem / grpc-ecosystem/grpc-spring

GRPC health check using actuator

Open
#1,091 2 comments 10 reactions 0 assignees View on GitHub
enhancement
Dominant language
Java
Stars
3.7k
Forks
858
PR merge metrics
No merged PRs in 30d

Description

**The problem**

I'm implementing a service that responds to GRPC and a custom protocol. For health-checking purposes, I need my application to consider the health status for both GRPC and the custom protocol. When implementing a custom health indicator for the custom protocol, I encountered an issue with the integration of Kubernetes GRPC health check probe ([link](https://github.com/grpc-ecosystem/grpc-health-probe)). The provided GRPC health check does not interact with the Spring Boot Actuator. The only way to interact with the existing GRPC health check is by manually updating the health status using [HealthServiceImpl](https://github.com/grpc/grpc-java/blob/master/services/src/main/java/io/grpc/services/HealthStatusManager.java#L35).

**The solution**

To address this, I've disabled the default health check GRPC binding and created a custom grpc handler for the healthcheck. This class translates Actuator's HealthEndpoint to GRPC format. While this solution is only partially compliant with the GRPC health protocol, as it lacks support for the Watch method, it sufficiently meets the requirements for Kubernetes deployment.
This is the code I am currently using.
```java

@RequiredArgsConstructor
public class ActuatorHealthCheckGrpc extends HealthImplBase {
private final HealthEndpoint healthEndpoint;

public void check(HealthCheckRequest request, StreamObserver responseObserver) {

if (!request.getService().isEmpty()) {
var health = healthEndpoint.healthForPath(request.getService());
if(health == null) {
responseObserver.onError(new StatusException(Status.NOT_FOUND.withDescription("unknown service " + request.getService())));
return;
}
var status = health.getStatus();
HealthCheckResponse.ServingStatus result = resolveStatus(status);
HealthCheckResponse response = HealthCheckResponse.newBuilder().setStatus(result).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
} else {

var status = healthEndpoint.health().getStatus();
HealthCheckResponse.ServingStatus result = resolveStatus(status);
HealthCheckResponse response = HealthCheckResponse.newBuilder().setStatus(result).build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}

}

private HealthCheckResponse.ServingStatus resolveStatus(org.springframework.boot.actuate.health.Status status) {
if (Objects.equals(org.springframework.boot.actuate.health.Status.UP.getCode(), status.getCode())) {
return HealthCheckResponse.ServingStatus.SERVING;
}
if (Objects.equals(org.springframework.boot.actuate.health.Status.DOWN.getCode(), status.getCode()) || Objects.equals(org.springframework.boot.actuate.health.Status.OUT_OF_SERVICE.getCode(), status.getCode())) {
return HealthCheckResponse.ServingStatus.NOT_SERVING;
}
return HealthCheckResponse.ServingStatus.UNKNOWN;
}
}
```

Considerations:

I explored an alternative to using HTTP health checks, but embedding an HTTP server in my application isn't desirable. Furthermore, I need help finding health indicators for the server in the repository; I haven't found any. Is the actuator considering the GRPC server's health using another approach?

I want to integrate something similar to this in this repository: a GRPC health implementation that allows the application to use an actuator health indicator. Would this be an acceptable solution even with the downsides presented?

Note: I welcome any feedback or suggestions on how to enhance this solution further.

Contributor guide

Open the contributing guide

Research direction

Start by reviewing the existing gRPC health binding and Spring Boot Actuator's HealthEndpoint, then compare them with the grpc-health-probe Check request and the proposed ActuatorHealthCheckGrpc implementation. Done means the gRPC health check can report the application's Actuator health, including requested service paths, with a clear decision on whether Watch support is required.

Written by the indexing model from the issue text.

Assessment

Tech stack
grpc, java, spring-boot
Domain
api, backend, observability
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.