Skip to content

Commit 712269f

Browse files
committed
Re-Add HealthStatusManager/grpc health service implementation
1 parent 31ea48c commit 712269f

File tree

9 files changed

+243
-13
lines changed

9 files changed

+243
-13
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2016-2021 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.server.autoconfigure;
19+
20+
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
22+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
23+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
24+
import org.springframework.context.annotation.Bean;
25+
import org.springframework.context.annotation.Configuration;
26+
27+
import io.grpc.BindableService;
28+
import io.grpc.protobuf.services.ProtoReflectionService;
29+
import io.grpc.services.HealthStatusManager;
30+
import net.devh.boot.grpc.server.service.GrpcService;
31+
32+
/**
33+
* Auto configuration that sets up the grpc health service.
34+
*
35+
* @author Daniel Theuke ([email protected])
36+
*/
37+
@Configuration
38+
@ConditionalOnClass(ProtoReflectionService.class)
39+
@ConditionalOnProperty(prefix = "grpc.server", name = "health-service-enabled", matchIfMissing = true)
40+
@AutoConfigureBefore(GrpcServerFactoryAutoConfiguration.class)
41+
public class GrpcHealthServiceAutoConfiguration {
42+
43+
/**
44+
* Creates a new HealthStatusManager instance.
45+
*
46+
* @return The newly created bean.
47+
*/
48+
@Bean
49+
@ConditionalOnMissingBean
50+
HealthStatusManager healthStatusManager() {
51+
return new HealthStatusManager();
52+
}
53+
54+
@Bean
55+
@GrpcService
56+
BindableService grpcHealthService(final HealthStatusManager healthStatusManager) {
57+
return healthStatusManager.getHealthService();
58+
}
59+
60+
}

grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/config/GrpcServerProperties.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,14 @@ public class GrpcServerProperties {
180180
@DataSizeUnit(DataUnit.BYTES)
181181
private DataSize maxInboundMetadataSize = null;
182182

183+
/**
184+
* Whether gRPC health service is enabled or not. Defaults to {@code true}.
185+
*
186+
* @param healthServiceEnabled Whether gRPC health service is enabled.
187+
* @return True, if the health service is enabled. False otherwise.
188+
*/
189+
private boolean healthServiceEnabled = true;
190+
183191
/**
184192
* Whether proto reflection service is enabled or not. Defaults to {@code true}.
185193
*

grpc-server-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# AutoConfiguration
22
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
33
net.devh.boot.grpc.server.autoconfigure.GrpcAdviceAutoConfiguration,\
4+
net.devh.boot.grpc.server.autoconfigure.GrpcHealthServiceAutoConfiguration,\
45
net.devh.boot.grpc.server.autoconfigure.GrpcMetadataConsulConfiguration,\
56
net.devh.boot.grpc.server.autoconfigure.GrpcMetadataEurekaConfiguration,\
67
net.devh.boot.grpc.server.autoconfigure.GrpcMetadataNacosConfiguration,\
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2016-2021 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.server.autoconfigure;
19+
20+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
23+
import org.junit.jupiter.api.Test;
24+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
25+
import org.springframework.boot.test.context.SpringBootTest;
26+
import org.springframework.test.annotation.DirtiesContext;
27+
28+
import io.grpc.ManagedChannel;
29+
import io.grpc.ManagedChannelBuilder;
30+
import io.grpc.health.v1.HealthCheckRequest;
31+
import io.grpc.health.v1.HealthCheckResponse;
32+
import io.grpc.health.v1.HealthCheckResponse.ServingStatus;
33+
import io.grpc.health.v1.HealthGrpc;
34+
import io.grpc.health.v1.HealthGrpc.HealthStub;
35+
36+
@SpringBootTest(classes = GrpcHealthServiceDefaultAutoConfigurationTest.TestConfig.class)
37+
@ImportAutoConfiguration({
38+
GrpcServerAutoConfiguration.class,
39+
GrpcServerFactoryAutoConfiguration.class,
40+
GrpcHealthServiceAutoConfiguration.class})
41+
@DirtiesContext
42+
class GrpcHealthServiceDefaultAutoConfigurationTest {
43+
44+
private static final HealthCheckRequest HEALTH_CHECK_REQUEST = HealthCheckRequest.getDefaultInstance();
45+
46+
@Test
47+
void testHealthService() {
48+
final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:9090").usePlaintext().build();
49+
try {
50+
final HealthStub stub = HealthGrpc.newStub(channel);
51+
52+
final AwaitableStreamObserver<HealthCheckResponse> resultObserver = new AwaitableStreamObserver<>();
53+
stub.check(HEALTH_CHECK_REQUEST, resultObserver);
54+
checkResult(resultObserver);
55+
} finally {
56+
channel.shutdown();
57+
}
58+
}
59+
60+
void checkResult(final AwaitableStreamObserver<HealthCheckResponse> resultObserver) {
61+
final HealthCheckResponse response = assertDoesNotThrow(resultObserver::getSingle);
62+
assertEquals(ServingStatus.SERVING, response.getStatus());
63+
}
64+
65+
static class TestConfig {
66+
}
67+
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) 2016-2021 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.server.autoconfigure;
19+
20+
import static org.assertj.core.api.Assertions.assertThat;
21+
import static org.assertj.core.api.InstanceOfAssertFactories.type;
22+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
23+
24+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
25+
import org.springframework.boot.test.context.SpringBootTest;
26+
import org.springframework.test.annotation.DirtiesContext;
27+
28+
import io.grpc.Status;
29+
import io.grpc.Status.Code;
30+
import io.grpc.StatusRuntimeException;
31+
import io.grpc.health.v1.HealthCheckResponse;
32+
33+
@SpringBootTest(classes = GrpcHealthServiceDefaultAutoConfigurationTest.TestConfig.class,
34+
properties = "grpc.server.health-service-enabled=false")
35+
@ImportAutoConfiguration({
36+
GrpcServerAutoConfiguration.class,
37+
GrpcServerFactoryAutoConfiguration.class,
38+
GrpcHealthServiceAutoConfiguration.class})
39+
@DirtiesContext
40+
class GrpcHealthServiceFalseAutoConfigurationTest extends GrpcHealthServiceDefaultAutoConfigurationTest {
41+
42+
@Override
43+
void checkResult(final AwaitableStreamObserver<HealthCheckResponse> resultObserver) {
44+
final Throwable error = assertDoesNotThrow(resultObserver::getError);
45+
assertThat(error).asInstanceOf(type(StatusRuntimeException.class))
46+
.extracting(StatusRuntimeException::getStatus)
47+
.extracting(Status::getCode)
48+
.isEqualTo(Code.UNIMPLEMENTED);
49+
}
50+
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2016-2021 Michael Zhang <[email protected]>
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
5+
* documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
6+
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following conditions:
8+
*
9+
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
10+
* Software.
11+
*
12+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
13+
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
14+
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
15+
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16+
*/
17+
18+
package net.devh.boot.grpc.server.autoconfigure;
19+
20+
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
21+
import org.springframework.boot.test.context.SpringBootTest;
22+
import org.springframework.test.annotation.DirtiesContext;
23+
24+
@SpringBootTest(classes = GrpcHealthServiceDefaultAutoConfigurationTest.TestConfig.class,
25+
properties = "grpc.server.health-service-enabled=true")
26+
@ImportAutoConfiguration({
27+
GrpcServerAutoConfiguration.class,
28+
GrpcServerFactoryAutoConfiguration.class,
29+
GrpcHealthServiceAutoConfiguration.class})
30+
@DirtiesContext
31+
class GrpcHealthServiceTrueAutoConfigurationTest extends GrpcHealthServiceDefaultAutoConfigurationTest {
32+
}

grpc-server-spring-boot-autoconfigure/src/test/java/net/devh/boot/grpc/server/autoconfigure/GrpcReflectionServiceDefaultAutoConfigurationTest.java

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,8 @@
3232
import io.grpc.reflection.v1alpha.ServerReflectionRequest;
3333
import io.grpc.reflection.v1alpha.ServerReflectionResponse;
3434
import io.grpc.stub.StreamObserver;
35-
import net.devh.boot.grpc.server.autoconfigure.GrpcReflectionServiceDefaultAutoConfigurationTest.TestConfig;
3635

37-
@SpringBootTest(classes = TestConfig.class)
36+
@SpringBootTest(classes = GrpcReflectionServiceDefaultAutoConfigurationTest.TestConfig.class)
3837
@ImportAutoConfiguration({
3938
GrpcServerAutoConfiguration.class,
4039
GrpcServerFactoryAutoConfiguration.class,
@@ -45,15 +44,19 @@ class GrpcReflectionServiceDefaultAutoConfigurationTest {
4544
@Test
4645
void testReflectionService() {
4746
final ManagedChannel channel = ManagedChannelBuilder.forTarget("localhost:9090").usePlaintext().build();
48-
final ServerReflectionStub stub = ServerReflectionGrpc.newStub(channel);
47+
try {
48+
final ServerReflectionStub stub = ServerReflectionGrpc.newStub(channel);
4949

50-
final AwaitableStreamObserver<ServerReflectionResponse> resultObserver = new AwaitableStreamObserver<>();
51-
final StreamObserver<ServerReflectionRequest> requestObserver = stub.serverReflectionInfo(resultObserver);
52-
requestObserver.onNext(ServerReflectionRequest.newBuilder()
53-
.setListServices("")
54-
.build());
55-
requestObserver.onCompleted();
56-
checkResult(resultObserver);
50+
final AwaitableStreamObserver<ServerReflectionResponse> resultObserver = new AwaitableStreamObserver<>();
51+
final StreamObserver<ServerReflectionRequest> requestObserver = stub.serverReflectionInfo(resultObserver);
52+
requestObserver.onNext(ServerReflectionRequest.newBuilder()
53+
.setListServices("")
54+
.build());
55+
requestObserver.onCompleted();
56+
checkResult(resultObserver);
57+
} finally {
58+
channel.shutdown();
59+
}
5760
}
5861

5962
void checkResult(final AwaitableStreamObserver<ServerReflectionResponse> resultObserver) {

tests/src/test/java/net/devh/boot/grpc/test/metric/MetricFullAutoConfigurationTest.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import org.springframework.test.annotation.DirtiesContext;
2828
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
2929

30+
import io.grpc.health.v1.HealthGrpc;
31+
import io.grpc.reflection.v1alpha.ServerReflectionGrpc;
3032
import io.micrometer.core.instrument.Counter;
3133
import io.micrometer.core.instrument.MeterRegistry;
3234
import io.micrometer.core.instrument.Timer;
@@ -48,8 +50,12 @@ class MetricFullAutoConfigurationTest {
4850
@Autowired
4951
private MeterRegistry meterRegistry;
5052

51-
private static final int REFLECTION_SERVER_METHOD_COUNT = 1;
52-
private static final int TOTAL_METHOD_COUNT = REFLECTION_SERVER_METHOD_COUNT + METHOD_COUNT;
53+
private static final int HEALTH_SERVICE_METHOD_COUNT =
54+
HealthGrpc.getServiceDescriptor().getMethods().size();
55+
private static final int REFLECTION_SERVICE_METHOD_COUNT =
56+
ServerReflectionGrpc.getServiceDescriptor().getMethods().size();
57+
private static final int TOTAL_METHOD_COUNT =
58+
HEALTH_SERVICE_METHOD_COUNT + REFLECTION_SERVICE_METHOD_COUNT + METHOD_COUNT;
5359

5460
@Test
5561
@DirtiesContext

tests/src/test/java/net/devh/boot/grpc/test/server/TestServiceImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636
import net.devh.boot.grpc.server.security.interceptors.AuthenticatingServerInterceptor;
3737
import net.devh.boot.grpc.server.service.GrpcService;
3838
import net.devh.boot.grpc.test.proto.SomeType;
39+
import net.devh.boot.grpc.test.proto.TestServiceGrpc;
3940
import net.devh.boot.grpc.test.proto.TestServiceGrpc.TestServiceImplBase;
4041

4142
@Slf4j
4243
@GrpcService
4344
public class TestServiceImpl extends TestServiceImplBase {
4445

45-
public static final int METHOD_COUNT = 8;
46+
public static final int METHOD_COUNT = TestServiceGrpc.getServiceDescriptor().getMethods().size();
4647

4748
public TestServiceImpl() {
4849
log.info("Created TestServiceImpl");

0 commit comments

Comments
 (0)