diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 4cd06597..ea04aab8 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,5 +1,23 @@ #!/usr/bin/env bash +# format code ./gradlew spotlessApply > /dev/null +# generate configuration properties docs +./gradlew classes > /dev/null +./gradlew generateConfigurationPropertiesDocs > /dev/null + +# escape {} in md +sed -i '' 's/{/\\{/g' build/configuration-properties.md + +# add sidebar_position +sed -i '' '1i\ +---\ +sidebar_position: 40\ +---\ +\ +' build/configuration-properties.md + +cp -f build/configuration-properties.md website/docs/40-configuration-properties.md + git add -u diff --git a/README.md b/README.md index 7d512cc4..f86f030d 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ [Documentation](https://danielliu1123.github.io/grpc-starter/) -[gRPC](https://grpc.io/) is a RPC framework, with support for robust features like -high-performance, multi-language support, concise service definition, streaming. -gRPC proves to be an ideal choice for building scalable and efficient microservice systems. +[gRPC](https://grpc.io/) is an RPC framework with robust features like high performance, +multi-language support, concise service definitions, and streaming. +It is an ideal choice for building scalable and efficient microservice systems. This project provides out-of-the-box, highly extensible Spring Boot starters for gRPC ecosystem. Make the integration of Spring Boot and gRPC feel seamless and native. diff --git a/build.gradle b/build.gradle index 928a7077..96915a2a 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,12 @@ +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath "org.rodnansol:spring-configuration-property-documenter-gradle-plugin:${springConfigurationPropertyDocumenterVersion}" + } +} + plugins { id "org.springframework.boot" version "${springBootVersion}" apply false id "io.spring.dependency-management" version "${springDependencyManagementVersion}" apply false @@ -15,9 +24,13 @@ allprojects { apply plugin: "java" apply plugin: "java-library" + sourceSets { + optionalSupport + } + java { - registerFeature("optionalSupport") { - usingSourceSet(sourceSets.main) + registerFeature("optionalSuppor") { + usingSourceSet(sourceSets.optionalSupport) } } @@ -82,3 +95,5 @@ allprojects { excludeFilter = file("${rootDir}/config/spotbugs/exclude.xml") } } + +apply from: "${rootDir}/gradle/generate-configuration-properties-docs.gradle" diff --git a/examples/transcoding/webflux/README.md b/examples/transcoding/webflux/README.md new file mode 100644 index 00000000..17ecdbd7 --- /dev/null +++ b/examples/transcoding/webflux/README.md @@ -0,0 +1,25 @@ +1. Start the application + + ```shell + ./gradlew :examples:transcoding:webflux:bootRun + ``` + +2. Use HTTP and gRPC clients to access the `Unary` api + + ```shell + curl -X POST -d '{"requestMessage": "World!"}' http://localhost:8080/unary + ``` + + ```shell + grpcurl -plaintext -d '{"requestMessage": "World!"}' localhost:9090 transcoding.flux.SimpleService/UnaryRpc + ``` + +3. Use HTTP and gRPC clients to access the `Server Streaming` api + + ```shell + curl http://localhost:8080/serverstreaming?requestMessage=World! + ``` + + ```shell + grpcurl -plaintext -d '{"requestMessage": "World!"}' localhost:9090 transcoding.flux.SimpleService/ServerStreamingRpc + ``` diff --git a/examples/transcoding/webmvc/README.md b/examples/transcoding/webmvc/README.md new file mode 100644 index 00000000..03c17f04 --- /dev/null +++ b/examples/transcoding/webmvc/README.md @@ -0,0 +1,25 @@ +1. Start the application + + ```shell + ./gradlew :examples:transcoding:webmvc:bootRun + ``` + +2. Use HTTP and gRPC clients to access the `Unary` api + + ```shell + curl -X POST -d '{"requestMessage": "World!"}' http://localhost:8080/unary + ``` + + ```shell + grpcurl -plaintext -d '{"requestMessage": "World!"}' localhost:9090 transcoding.mvc.SimpleService/UnaryRpc + ``` + +3. Use HTTP and gRPC clients to access the `Server Streaming` api + + ```shell + curl http://localhost:8080/serverstreaming?requestMessage=World! + ``` + + ```shell + grpcurl -plaintext -d '{"requestMessage": "World!"}' localhost:9090 transcoding.mvc.SimpleService/ServerStreamingRpc + ``` diff --git a/examples/transcoding/webmvc/src/main/proto/simpleservice.proto b/examples/transcoding/webmvc/src/main/proto/simpleservice.proto index 82a8909d..90d7cb2f 100644 --- a/examples/transcoding/webmvc/src/main/proto/simpleservice.proto +++ b/examples/transcoding/webmvc/src/main/proto/simpleservice.proto @@ -4,9 +4,15 @@ import "google/api/annotations.proto"; package transcoding.mvc; -// A simple service for test. +message SimpleRequest { + string requestMessage = 1; +} + +message SimpleResponse { + string responseMessage = 1; +} + service SimpleService { - // Simple unary RPC. rpc UnaryRpc (SimpleRequest) returns (SimpleResponse) { option (google.api.http) = { post: "/unary", @@ -14,22 +20,9 @@ service SimpleService { }; } - // Simple server-to-client streaming RPC. rpc ServerStreamingRpc (SimpleRequest) returns (stream SimpleResponse) { option (google.api.http) = { get: "/serverstreaming" }; } } - -// A simple request message type for test. -message SimpleRequest { - // An optional string message for test. - string requestMessage = 1; -} - -// A simple response message type for test. -message SimpleResponse { - // An optional string message for test. - string responseMessage = 1; -} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index fbe09a77..1b74d078 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,6 +10,9 @@ springCloudContextVersion=4.1.3 # https://github.com/spring-gradle-plugins/dependency-management-plugin springDependencyManagementVersion=1.1.5 +# https://github.com/rodnansol/spring-configuration-property-documenter/blob/master/docs/modules/ROOT/pages/gradle-plugin.adoc +springConfigurationPropertyDocumenterVersion=0.7.1 + # gRPC related # https://github.com/google/protobuf-gradle-plugin protobufGradlePluginVersion=0.9.4 diff --git a/gradle/generate-configuration-properties-docs.gradle b/gradle/generate-configuration-properties-docs.gradle new file mode 100644 index 00000000..2791c9eb --- /dev/null +++ b/gradle/generate-configuration-properties-docs.gradle @@ -0,0 +1,54 @@ +apply plugin: "org.rodnansol.spring-configuration-property-documenter" + +// see https://github.com/rodnansol/spring-configuration-property-documenter/blob/master/docs/modules/ROOT/pages/gradle-plugin.adoc#multi-module-multiple-sub-projects +tasks.register('generateConfigurationPropertiesDocs') { + dependsOn generateAndAggregateDocuments { + documentName = "Configuration Properties" + documentDescription = """ +Configuration properties for the gRPC starter project. + +This page was generated by [spring-configuration-property-documenter](https://github.com/rodnansol/spring-configuration-property-documenter/blob/master/docs/modules/ROOT/pages/gradle-plugin.adoc). +""" + type = "MARKDOWN" + + metadataInputs { + metadata { + name = "grpc-client-boot-autoconfigure" + input = file("grpc-boot-autoconfigure/grpc-client-boot-autoconfigure") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-server-boot-autoconfigure" + input = file("grpc-boot-autoconfigure/grpc-server-boot-autoconfigure") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-metrics" + input = file("grpc-extensions/grpc-metrics") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-test" + input = file("grpc-extensions/grpc-test") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-tracing" + input = file("grpc-extensions/grpc-tracing") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-transcoding" + input = file("grpc-extensions/grpc-transcoding") + excludedGroups = ["Unknown group"] + } + metadata { + name = "grpc-validation" + input = file("grpc-extensions/grpc-validation") + excludedGroups = ["Unknown group"] + } + } + + outputFile = new File("build/configuration-properties.md") + } +} diff --git a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java index f2bdb3c0..a63f01af 100644 --- a/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java +++ b/grpc-boot-autoconfigure/grpc-client-boot-autoconfigure/src/main/java/grpcstarter/client/GrpcClientProperties.java @@ -34,24 +34,25 @@ public class GrpcClientProperties implements InitializingBean { public static final String PREFIX = "grpc.client"; /** - * Whether to enable gRPC client autoconfiguration, default {@code true}. + * Whether to enable gRPC client autoconfiguration, default true. */ private boolean enabled = true; /** * Default authority. * - *
e.g. {@code localhost:8080} + *
e.g. localhost:8080
*/ private String authority; /** * Base packages to scan for gRPC stubs. * - *This value will merge with {@link EnableGrpcClients#basePackages}, only takes effect if {@link EnableGrpcClients#basePackages} is not set. - *
The advantage of using configuration is no need to introduce external annotations. + *
This value will merge with {@link EnableGrpcClients#basePackages}, only takes effect if {@link EnableGrpcClients#basePackages} is not set.
+ * + *The advantage of using configuration is no need to introduce external annotations.
*/ private ListThis is a more IDE-friendly alternative to {@link #services}/{@link #stubs}, using classes first if both set. + *
This is a more IDE-friendly alternative to {@link #services}/{@link #stubs}, using classes first if both set.
* - *The priority is classes > {@link #stubs} > {@link #services}. + *
The priority is classes > {@link #stubs} > {@link #services}.
*/ @SuppressWarnings("rawtypes") private ListSupport Ant-style patterns. + *
Support Ant-style patterns.
* - *e.g. {@link HealthGrpc.HealthBlockingStub} can be identified by + *
e.g. {@link HealthGrpc.HealthBlockingStub} can be identified by
*This is a more flexible alternative to {@link #classes}, using {@link #classes} first if both set. + *
This is a more flexible alternative to {@link #classes}, using {@link #classes} first if both set.
* - *The priority is {@link #classes} > stubs > {@link #services}. + *
The priority is {@link #classes} > stubs > {@link #services}.
*/ private ListSupport Ant-style patterns. + *
Support Ant-style patterns.
* - *e.g. {@link HealthGrpc.HealthBlockingStub} can be identified by + *
e.g. {@link HealthGrpc.HealthBlockingStub} can be identified by
*This is a more flexible alternative to {@link #classes}, using {@link #classes} first if both set. + *
This is a more flexible alternative to {@link #classes}, using {@link #classes} first if both set.
* - *The priority is {@link #classes} > {@link #stubs} > services. + *
The priority is {@link #classes} > {@link #stubs} > services.
* * @see AntPathMatcher */ @@ -245,7 +246,7 @@ public static class InProcess { /** * In-process client name. * - *If set, will create an in-process channel by default, usually for testing. + *
If set, will create an in-process channel by default, usually for testing.
*/ private String name; } @@ -285,9 +286,9 @@ public static class Refresh { public static final String PREFIX = GrpcClientProperties.PREFIX + ".refresh"; /** - * Whether to enable refresh grpc clients, default {@code false}. + * Whether to enable refresh grpc clients, default false. * - *NOTE: this feature needs {@code spring-cloud-context} dependency in the classpath. + *
NOTE: this feature needs 'spring-cloud-context' dependency in the classpath.
*/ private boolean enabled = false; } diff --git a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java index 05f3fdd8..9d39b833 100644 --- a/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java +++ b/grpc-boot-autoconfigure/grpc-server-boot-autoconfigure/src/main/java/grpcstarter/server/GrpcServerProperties.java @@ -24,19 +24,19 @@ public class GrpcServerProperties { public static final String PREFIX = "grpc.server"; /** - * Whether to enable gRPC server autoconfiguration, default {@code true}. + * Whether to enable gRPC server autoconfiguration, default true. */ private boolean enabled = true; /** - * gRPC server port, default {@code 9090}, {@code 0} or negative number will use random port. + * gRPC server port, default 9090, 0 or negative numbers will use random port. */ private int port = 9090; /** - * Graceful shutdown timeout, default {@code 30s}, if {@code 0} will wait forever util all active calls finished. + * Graceful shutdown timeout, default 30s, if 0 will wait forever util all active calls finished. */ private long shutdownTimeout = 30000L; /** - * Whether to start a gRPC server when no service found, default {@code true}. + * Whether to start a gRPC server when no service found, default true. */ private boolean enableEmptyServer = true; /** @@ -56,13 +56,13 @@ public class GrpcServerProperties { */ private ExceptionHandling exceptionHandling = new ExceptionHandling(); /** - * The maximum message size allowed to be received on the server, default {@code 4MB}. + * The maximum message size allowed to be received on the server, default 4MB. * * @see GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE */ private DataSize maxInboundMessageSize; /** - * The maximum size of metadata allowed to be received, default {@code 8KB}. + * The maximum size of metadata allowed to be received, default 8KB. * * @see GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE */ @@ -85,7 +85,7 @@ public static class Reflection { public static final String PREFIX = GrpcServerProperties.PREFIX + ".reflection"; /** - * Whether to register reflection service, default {@code false}. + * Whether to register reflection service, default false. */ private boolean enabled = false; } @@ -95,7 +95,7 @@ public static class Health { public static final String PREFIX = GrpcServerProperties.PREFIX + ".health"; /** - * Whether to enable health check, default {@code false} + * Whether to enable health check, default false. */ private boolean enabled = true; @@ -114,15 +114,15 @@ public static class DataSource { public static final String PREFIX = Health.PREFIX + ".datasource"; /** - * Whether to enable datasource health check, default {@code true}. + * Whether to enable datasource health check, default true. */ private boolean enabled = true; /** - * The service name that will be used for datasource health check, default {@code datasource}. + * The service name that will be used for datasource health check, default value is 'datasource'. */ private String service = "datasource"; /** - * The SQL query that will be used to validate datasource connection, default {@code SELECT 1}. + * The SQL query that will be used to validate datasource connection, default value is 'SELECT 1'. */ private String validationQuery = "SELECT 1"; /** @@ -136,11 +136,11 @@ public static class Redis { public static final String PREFIX = Health.PREFIX + ".redis"; /** - * Whether to enable redis health check, default {@code true}. + * Whether to enable redis health check, default true. */ private boolean enabled = true; /** - * The service name that will be used for redis health check, default {@code redis}. + * The service name that will be used for redis health check, default value is 'redis'. */ private String service = "redis"; } @@ -151,11 +151,11 @@ public static class Channelz { public static final String PREFIX = GrpcServerProperties.PREFIX + ".channelz"; /** - * Whether to register {@link ChannelzService}, default {@code false}. + * Whether to register {@link ChannelzService}, default false. */ private boolean enabled = false; /** - * The maximum page size to return, default {@code 100} + * The maximum page size to return, default 100. * * @see AdminInterface */ @@ -167,21 +167,21 @@ public static class ExceptionHandling { public static final String PREFIX = GrpcServerProperties.PREFIX + ".exception-handling"; /** - * Whether to enable exception handling, default {@code true} + * Whether to enable exception handling, default true. */ private boolean enabled = true; /** - * Whether to enable {@link DefaultGrpcExceptionAdvice}, default {@code true}. + * Whether to enable {@link DefaultGrpcExceptionAdvice}, default true. * - *{@link DefaultGrpcExceptionAdvice} will handle exceptions recognized by gRPC, including: + *
{@link DefaultGrpcExceptionAdvice} will handle exceptions recognized by gRPC, including:
*When enabled, you can directly throw {@link StatusRuntimeException} or {@link StatusException} in service implementation, - * and the exception will be handled by {@link DefaultGrpcExceptionAdvice}. + * and the exception will be handled by {@link DefaultGrpcExceptionAdvice}.
* *{@code * @GrpcService @@ -254,7 +254,7 @@ public static class Response { /** * The maximum length of response description. * - *When the length of the description exceeds this value, it will be truncated. + *
When the length of the description exceeds this value, it will be truncated.
* * @since 3.2.3 */ diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java index c743ebf1..5a404fd7 100644 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingAutoConfiguration.java @@ -3,13 +3,11 @@ import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.REACTIVE; import static org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type.SERVLET; -import grpcstarter.server.GrpcServerCustomizer; +import grpcstarter.server.ConditionOnGrpcServerEnabled; import grpcstarter.server.GrpcServerProperties; import io.grpc.BindableService; import io.grpc.Metadata; -import io.grpc.ServerInterceptor; import java.util.List; -import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -23,37 +21,30 @@ * @author Freeman */ @Configuration(proxyBeanMethods = false) -@ConditionalOnClass({Metadata.class, HttpHeaders.class}) +@ConditionalOnClass({Metadata.class, HttpHeaders.class, GrpcServerProperties.class}) @ConditionalOnProperty(prefix = GrpcTranscodingProperties.PREFIX, name = "enabled", matchIfMissing = true) +@ConditionOnGrpcServerEnabled @EnableConfigurationProperties(GrpcTranscodingProperties.class) public class GrpcTranscodingAutoConfiguration { @Bean @ConditionalOnMissingBean - public HeaderConverter defaultHeaderConverter() { + public HeaderConverter defaultGrpcTranscodingHeaderConverter() { return new DefaultHeaderConverter(); } - @Bean - @ConditionalOnMissingBean - public TranscodingGrpcServer transcodingGrpcServer( - GrpcServerProperties properties, - GrpcTranscodingProperties transcodingProperties, - ObjectProviderserviceProvider, - ObjectProvider interceptorProvider, - ObjectProvider customizers) { - return new TranscodingGrpcServer( - properties, serviceProvider, interceptorProvider, customizers, transcodingProperties); - } - @Configuration(proxyBeanMethods = false) @ConditionalOnWebApplication(type = SERVLET) static class WebMvc { @Bean public ServletTranscodingRouterFunction webMvcTranscodingRouterFunction( - List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { - return new ServletTranscodingRouterFunction(services, headerConverter, properties); + List services, + HeaderConverter headerConverter, + GrpcTranscodingProperties grpcTranscodingProperties, + GrpcServerProperties grpcServerProperties) { + return new ServletTranscodingRouterFunction( + services, headerConverter, grpcTranscodingProperties, grpcServerProperties); } } @@ -63,8 +54,12 @@ static class WebFlux { @Bean public ReactiveTranscodingRouterFunction webFluxTranscodingRouterFunction( - List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { - return new ReactiveTranscodingRouterFunction(services, headerConverter, properties); + List services, + HeaderConverter headerConverter, + GrpcTranscodingProperties grpcTranscodingProperties, + GrpcServerProperties grpcServerProperties) { + return new ReactiveTranscodingRouterFunction( + services, headerConverter, grpcTranscodingProperties, grpcServerProperties); } } } diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java index 5300d26a..060c1e6f 100644 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/GrpcTranscodingProperties.java @@ -1,6 +1,5 @@ package grpcstarter.extensions.transcoding; -import java.util.UUID; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; @@ -18,7 +17,7 @@ public class GrpcTranscodingProperties { private boolean enabled = true; /** - * In-process name for gRPC transcoding server, default is a random UUID. + * gRPC server endpoint, if not set, will use {@code localhost:${grpc.server.port}}. */ - private String inProcessName = UUID.randomUUID().toString(); + private String endpoint; } diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java index 9261a4d3..65a4e92d 100644 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ReactiveTranscodingRouterFunction.java @@ -4,8 +4,8 @@ import static grpcstarter.extensions.transcoding.TranscodingUtil.toHttpStatus; import static grpcstarter.extensions.transcoding.Util.URI_TEMPLATE_VARIABLES_ATTRIBUTE; import static grpcstarter.extensions.transcoding.Util.buildRequestMessage; -import static grpcstarter.extensions.transcoding.Util.getInProcessChannel; import static grpcstarter.extensions.transcoding.Util.getReactiveRoutes; +import static grpcstarter.extensions.transcoding.Util.getTranscodingChannel; import static grpcstarter.extensions.transcoding.Util.shutdown; import static grpcstarter.extensions.transcoding.Util.trim; import static io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING; @@ -15,6 +15,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import grpcstarter.extensions.transcoding.Util.Route; +import grpcstarter.server.GrpcServerProperties; import io.grpc.BindableService; import io.grpc.CallOptions; import io.grpc.Channel; @@ -67,31 +68,36 @@ public class ReactiveTranscodingRouterFunction * * e.g. "grpc.testing.SimpleService/UnaryRpc" -> Route */ - private final Map
> methodNameRoutes = new HashMap<>(); + private final Map > fullMethodNameToRoute = new HashMap<>(); private final List > routes = new ArrayList<>(); private final HeaderConverter headerConverter; private final GrpcTranscodingProperties properties; + private final GrpcServerProperties grpcServerProperties; private Channel channel; public ReactiveTranscodingRouterFunction( - List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { - getReactiveRoutes(services, methodNameRoutes, routes); + List services, + HeaderConverter headerConverter, + GrpcTranscodingProperties properties, + GrpcServerProperties grpcServerProperties) { + getReactiveRoutes(services, fullMethodNameToRoute, routes); this.headerConverter = headerConverter; this.properties = properties; + this.grpcServerProperties = grpcServerProperties; } @Override public void afterSingletonsInstantiated() { - channel = getInProcessChannel(properties.getInProcessName()); + channel = getTranscodingChannel(properties, grpcServerProperties); } @Override @Nonnull public Mono > route(@Nonnull ServerRequest request) { if (Objects.equals(request.method(), HttpMethod.POST)) { - var route = methodNameRoutes.get(trim(request.path(), '/')); + var route = fullMethodNameToRoute.get(trim(request.path(), '/')); if (route != null) { request.attributes().put(MATCHING_ROUTE, route); return Mono.just(this); diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java index d87e2074..5eadbb64 100644 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/ServletTranscodingRouterFunction.java @@ -6,7 +6,8 @@ import static grpcstarter.extensions.transcoding.Util.URI_TEMPLATE_VARIABLES_ATTRIBUTE; import static grpcstarter.extensions.transcoding.Util.buildRequestMessage; import static grpcstarter.extensions.transcoding.Util.fillRoutes; -import static grpcstarter.extensions.transcoding.Util.getInProcessChannel; +import static grpcstarter.extensions.transcoding.Util.getTranscodingChannel; +import static grpcstarter.extensions.transcoding.Util.shutdown; import static grpcstarter.extensions.transcoding.Util.trim; import static io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING; import static io.grpc.MethodDescriptor.MethodType.UNARY; @@ -15,6 +16,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; +import grpcstarter.server.GrpcServerProperties; import io.grpc.BindableService; import io.grpc.CallOptions; import io.grpc.Channel; @@ -36,6 +38,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicReference; import lombok.SneakyThrows; +import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -50,7 +53,10 @@ * @since 3.3.0 */ public class ServletTranscodingRouterFunction - implements RouterFunction , HandlerFunction , SmartInitializingSingleton { + implements RouterFunction , + HandlerFunction , + SmartInitializingSingleton, + DisposableBean { private static final String MATCHING_ROUTE = ServletTranscodingRouterFunction.class + ".matchingRoute"; @@ -59,31 +65,36 @@ public class ServletTranscodingRouterFunction * * e.g. "grpc.testing.SimpleService/UnaryRpc" -> Route */ - private final Map
> methodNameRoutes = new HashMap<>(); + private final Map > fullMethodNameToRoute = new HashMap<>(); private final List > routes = new ArrayList<>(); private final HeaderConverter headerConverter; private final GrpcTranscodingProperties properties; + private final GrpcServerProperties grpcServerProperties; private Channel channel; public ServletTranscodingRouterFunction( - List services, HeaderConverter headerConverter, GrpcTranscodingProperties properties) { - fillRoutes(services, methodNameRoutes, routes); + List services, + HeaderConverter headerConverter, + GrpcTranscodingProperties properties, + GrpcServerProperties grpcServerProperties) { + fillRoutes(services, fullMethodNameToRoute, routes); this.headerConverter = headerConverter; this.properties = properties; + this.grpcServerProperties = grpcServerProperties; } @Override public void afterSingletonsInstantiated() { - channel = getInProcessChannel(properties.getInProcessName()); + channel = getTranscodingChannel(properties, grpcServerProperties); } @Override @Nonnull public Optional > route(@Nonnull ServerRequest request) { if (Objects.equals(request.method(), HttpMethod.POST)) { - var route = methodNameRoutes.get(trim(request.path(), '/')); + var route = fullMethodNameToRoute.get(trim(request.path(), '/')); if (route != null) { request.attributes().put(MATCHING_ROUTE, route); return Optional.of(this); @@ -219,4 +230,9 @@ private static Message getMessage(Route> route, Transcoder transcoder) { throw new ResponseStatusException(BAD_REQUEST, e.getMessage(), e); } } + + @Override + public void destroy() throws Exception { + shutdown(channel, Duration.ofSeconds(15)); + } } diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java deleted file mode 100644 index a31d9b38..00000000 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/TranscodingGrpcServer.java +++ /dev/null @@ -1,153 +0,0 @@ -package grpcstarter.extensions.transcoding; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; -import grpcstarter.server.GrpcServerCustomizer; -import grpcstarter.server.GrpcServerProperties; -import io.grpc.BindableService; -import io.grpc.Server; -import io.grpc.ServerBuilder; -import io.grpc.ServerInterceptor; -import io.grpc.inprocess.InProcessServerBuilder; -import java.io.IOException; -import java.util.Optional; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.ObjectProvider; -import org.springframework.context.SmartLifecycle; -import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.util.unit.DataSize; - -/** - * @author Freeman - * @since 3.3.0 - */ -public class TranscodingGrpcServer implements SmartLifecycle { - private static final Logger log = LoggerFactory.getLogger(TranscodingGrpcServer.class); - - private final Server server; - private final AtomicBoolean isRunning = new AtomicBoolean(false); - private final CountDownLatch latch = new CountDownLatch(1); - private final GrpcServerProperties properties; - private final GrpcTranscodingProperties transcodingProperties; - - @SuppressFBWarnings("CT_CONSTRUCTOR_THROW") - public TranscodingGrpcServer( - GrpcServerProperties properties, - ObjectProvider serviceProvider, - ObjectProvider interceptorProvider, - ObjectProvider customizers, - GrpcTranscodingProperties transcodingProperties) { - this.properties = properties; - this.transcodingProperties = transcodingProperties; - this.server = - buildGrpcServer(properties, transcodingProperties, serviceProvider, interceptorProvider, customizers); - } - - private static Server buildGrpcServer( - GrpcServerProperties properties, - GrpcTranscodingProperties transcodingProperties, - ObjectProvider serviceProvider, - ObjectProvider interceptorProvider, - ObjectProvider customizers) { - ServerBuilder> builder = InProcessServerBuilder.forName(transcodingProperties.getInProcessName()); - - // add services - serviceProvider.forEach(builder::addService); - - // add interceptors, gRPC applies interceptors in reversed order - interceptorProvider.stream() - .sorted(AnnotationAwareOrderComparator.INSTANCE.reversed()) - .forEach(builder::intercept); - - Optional.ofNullable(properties.getMaxInboundMessageSize()) - .map(DataSize::toBytes) - .map(Long::intValue) - .ifPresent(builder::maxInboundMessageSize); - Optional.ofNullable(properties.getMaxInboundMetadataSize()) - .map(DataSize::toBytes) - .map(Long::intValue) - .ifPresent(builder::maxInboundMetadataSize); - - // apply customizers - customizers.orderedStream().forEach(customizer -> customizer.customize(builder)); - - return builder.build(); - } - - @Override - public void start() { - if (isRunning()) { - return; - } - try { - server.start(); - isRunning.set(true); - if (log.isInfoEnabled()) { - log.info("gRPC transcoding in-process server started: {}", transcodingProperties.getInProcessName()); - } - - waitUntilShutdown(); - } catch (IOException e) { - gracefulShutdown(); - throw new IllegalStateException(e); - } - } - - @Override - public void stop() { - if (isRunning.get()) { - gracefulShutdown(); - isRunning.set(false); - latch.countDown(); - } - } - - @Override - public boolean isRunning() { - return isRunning.get(); - } - - private void waitUntilShutdown() { - new Thread( - () -> { - try { - // wait here until terminating - latch.await(); - } catch (InterruptedException e) { - log.warn("gRPC transcoding server await termination interrupted", e); - Thread.currentThread().interrupt(); - } - }, - "grpc-transcoding-termination-awaiter") - .start(); - } - - private void gracefulShutdown() { - long start = System.currentTimeMillis(); - - // stop accepting new calls - server.shutdown(); - - try { - long time = properties.getShutdownTimeout(); - if (time > 0L) { - server.awaitTermination(time, TimeUnit.MILLISECONDS); - } else { - server.awaitTermination(); - } - } catch (InterruptedException e) { - log.warn("gRPC transcoding server graceful shutdown interrupted", e); - Thread.currentThread().interrupt(); - } - if (!server.isTerminated()) { - server.shutdownNow(); - } - - if (log.isInfoEnabled()) { - log.info("gRPC transcoding server graceful shutdown in {} ms", System.currentTimeMillis() - start); - } - } -} diff --git a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java index 1d83f7a6..8d54dd5b 100644 --- a/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java +++ b/grpc-extensions/grpc-transcoding/src/main/java/grpcstarter/extensions/transcoding/Util.java @@ -17,9 +17,11 @@ import com.google.protobuf.UInt32Value; import com.google.protobuf.UInt64Value; import com.google.protobuf.Value; +import grpcstarter.server.GrpcServerProperties; import io.grpc.BindableService; import io.grpc.Channel; import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; import io.grpc.MethodDescriptor; import io.grpc.ServerMethodDefinition; import io.grpc.ServerServiceDefinition; @@ -45,6 +47,7 @@ import org.springframework.http.HttpMethod; import org.springframework.util.ConcurrentReferenceHashMap; import org.springframework.util.StringUtils; +import org.springframework.util.unit.DataSize; import org.springframework.web.servlet.function.ServerRequest; /** @@ -56,6 +59,9 @@ class Util { public static final String URI_TEMPLATE_VARIABLES_ATTRIBUTE = Util.class + ".matchingPattern"; + private static final HttpRule defaultHttpRule = + HttpRule.newBuilder().setBody("*").build(); + /** * Cache for the default message of the method input type. * @@ -89,12 +95,7 @@ private static List > fillRoutes( methodNameRoutes.put( invokeMethod.getFullMethodName(), - new Route<>( - HttpRule.newBuilder().setBody("*").build(), - invokeMethod, - methodDescriptor, - t -> false, - List.of())); + new Route<>(defaultHttpRule, invokeMethod, methodDescriptor, t -> false, List.of())); if (methodDescriptor.getOptions().hasExtension(AnnotationsProto.http)) { HttpRule httpRule = methodDescriptor.getOptions().getExtension(AnnotationsProto.http); @@ -275,9 +276,39 @@ public static String getClassName(Descriptors.Descriptor descriptor) { return className; } - public static ManagedChannel getInProcessChannel(String name) { - // TODO(Freeman): set max message size? - return InProcessChannelBuilder.forName(name).usePlaintext().build(); + public static Channel getTranscodingChannel( + GrpcTranscodingProperties grpcTranscodingProperties, GrpcServerProperties grpcServerProperties) { + var inProcess = grpcServerProperties.getInProcess(); + if (inProcess != null && StringUtils.hasText(inProcess.getName())) { + InProcessChannelBuilder b = InProcessChannelBuilder.forName(inProcess.getName()); + return populateChannel(b, grpcServerProperties); + } + + String endpoint = StringUtils.hasText(grpcTranscodingProperties.getEndpoint()) + ? grpcTranscodingProperties.getEndpoint() + : "localhost:" + grpcServerProperties.getPort(); + var b = ManagedChannelBuilder.forTarget(endpoint); + return populateChannel(b, grpcServerProperties); + } + + private static Channel populateChannel( + ManagedChannelBuilder extends ManagedChannelBuilder>> channelBuilder, + GrpcServerProperties grpcServerProperties) { + + Optional.ofNullable(grpcServerProperties.getMaxInboundMessageSize()) + .map(DataSize::toBytes) + .map(Long::intValue) + .ifPresent(channelBuilder::maxInboundMessageSize); + Optional.ofNullable(grpcServerProperties.getMaxInboundMetadataSize()) + .map(DataSize::toBytes) + .map(Long::intValue) + .ifPresent(channelBuilder::maxInboundMetadataSize); + + if (grpcServerProperties.getTls() == null) { + channelBuilder.usePlaintext(); + } + + return channelBuilder.build(); } public static Message buildRequestMessage(Transcoder transcoder, Route> route) diff --git a/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java b/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java deleted file mode 100644 index 9cc5d952..00000000 --- a/grpc-extensions/grpc-transcoding/src/test/java/grpcstarter/extensions/transcoding/Deps.java +++ /dev/null @@ -1,14 +0,0 @@ -package grpcstarter.extensions.transcoding; - -/** - * @author Freeman - */ -public class Deps { - - public static final String SPRING_BOOT_VERSION = "3.2.4"; - - public static final String WEB_MVC_STARTER = - "org.springframework.boot:spring-boot-starter-web:" + SPRING_BOOT_VERSION; - public static final String WEB_FLUX_STARTER = - "org.springframework.boot:spring-boot-starter-webflux:" + SPRING_BOOT_VERSION; -} diff --git a/website/docs/30-extensions/10-grpc-http-transcoding.mdx b/website/docs/30-extensions/10-grpc-http-transcoding.mdx index 545409cc..9e05ae35 100644 --- a/website/docs/30-extensions/10-grpc-http-transcoding.mdx +++ b/website/docs/30-extensions/10-grpc-http-transcoding.mdx @@ -208,7 +208,7 @@ public class CustomHeaderConverter implements HeaderConverter { ## Configurations -If you want to disable the transcoding, use the following configuration: +Disable transcoding: ```yaml grpc: @@ -216,22 +216,25 @@ grpc: enabled: false ``` -Custom gRPC transcoding in-process server name: +Custom gRPC server endpoint: ```yaml grpc: transcoding: - in-process-name: whatever + endpoint: localhost:9090 ``` +In most cases, you do not need to manually configure this property, +it will automatically find the gRPC server endpoint of the current application. + ## How It Works 1. When the application starts up, it will get all the protobuf configurations for HTTP mapping (google.api.http), and then register them into the internally implemented [`RouterFunction`](https://docs.spring.io/spring-framework/reference/web/webmvc-functional.html#webmvc-fn-overview). -2. The application will start an in-process gRPC server specifically to handle transcoding requests. - -3. When an HTTP request comes in, the `RouterFunction` will find the corresponding gRPC service based on the request’s URL and method, +2. When an HTTP request comes in, the `RouterFunction` will find the corresponding gRPC service based on the request’s URL and method, then convert the HTTP request into a gRPC request, -send it to the in-process gRPC server, and finally convert the gRPC response back into an HTTP response to return. +send it to the gRPC server endpoint, and finally convert the gRPC response back into an HTTP response to return. + +Refer to [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway?tab=readme-ov-file#about) for more details. diff --git a/website/docs/30-extensions/50-test.mdx b/website/docs/30-extensions/50-test.mdx index 62008394..9b990310 100644 --- a/website/docs/30-extensions/50-test.mdx +++ b/website/docs/30-extensions/50-test.mdx @@ -32,7 +32,7 @@ This extension integrates `@SpringBootTest` for better testing experience. ### @InProcessName -After adding the dependency, the gRPC server will use in-process by default. +After adding the dependency, the gRPC server will **use in-process by default**. Get the in-process name using the `@InProcessName` annotation: diff --git a/website/docs/40-configuration-properties.md b/website/docs/40-configuration-properties.md new file mode 100644 index 00000000..45c3816d --- /dev/null +++ b/website/docs/40-configuration-properties.md @@ -0,0 +1,311 @@ +--- +sidebar_position: 40 +--- + +# Configuration Properties + +Configuration properties for the gRPC starter project. + +This page was generated by [spring-configuration-property-documenter](https://github.com/rodnansol/spring-configuration-property-documenter/blob/master/docs/modules/ROOT/pages/gradle-plugin.adoc). + +## Table of Contents +* [**grpc-client-boot-autoconfigure**](#grpc-client-boot-autoconfigure) + * [**grpc.client.tls.key-manager** - `grpcstarter.client.GrpcClientProperties$Tls$KeyManager`](#grpc.client.tls.key-manager) + + * [**grpc.client.tls.trust-manager** - `grpcstarter.client.GrpcClientProperties$Tls$TrustManager`](#grpc.client.tls.trust-manager) + + * [**grpc.client** - `grpcstarter.client.GrpcClientProperties`](#grpc.client) + + * [**grpc.client.in-process** - `grpcstarter.client.GrpcClientProperties$InProcess`](#grpc.client.in-process) + + * [**grpc.client.refresh** - `grpcstarter.client.GrpcClientProperties$Refresh`](#grpc.client.refresh) + + * [**grpc.client.retry** - `grpcstarter.client.GrpcClientProperties$Retry`](#grpc.client.retry) + + * [**grpc.client.tls** - `grpcstarter.client.GrpcClientProperties$Tls`](#grpc.client.tls) +* [**grpc-server-boot-autoconfigure**](#grpc-server-boot-autoconfigure) + * [**grpc.server.tls.key-manager** - `grpcstarter.server.GrpcServerProperties$Tls$KeyManager`](#grpc.server.tls.key-manager) + + * [**grpc.server.tls.trust-manager** - `grpcstarter.server.GrpcServerProperties$Tls$TrustManager`](#grpc.server.tls.trust-manager) + + * [**grpc.server.health.datasource** - `grpcstarter.server.GrpcServerProperties$Health$DataSource`](#grpc.server.health.datasource) + + * [**grpc.server.health.redis** - `grpcstarter.server.GrpcServerProperties$Health$Redis`](#grpc.server.health.redis) + + * [**grpc.server** - `grpcstarter.server.GrpcServerProperties`](#grpc.server) + + * [**grpc.server.channelz** - `grpcstarter.server.GrpcServerProperties$Channelz`](#grpc.server.channelz) + + * [**grpc.server.exception-handling** - `grpcstarter.server.GrpcServerProperties$ExceptionHandling`](#grpc.server.exception-handling) + + * [**grpc.server.health** - `grpcstarter.server.GrpcServerProperties$Health`](#grpc.server.health) + + * [**grpc.server.in-process** - `grpcstarter.server.GrpcServerProperties$InProcess`](#grpc.server.in-process) + + * [**grpc.server.reflection** - `grpcstarter.server.GrpcServerProperties$Reflection`](#grpc.server.reflection) + + * [**grpc.server.response** - `grpcstarter.server.GrpcServerProperties$Response`](#grpc.server.response) + + * [**grpc.server.tls** - `grpcstarter.server.GrpcServerProperties$Tls`](#grpc.server.tls) +* [**grpc-metrics**](#grpc-metrics) + * [**grpc.metrics** - `grpcstarter.extensions.metrics.GrpcMetricsProperties`](#grpc.metrics) + + * [**grpc.metrics.client** - `grpcstarter.extensions.metrics.GrpcMetricsProperties$Client`](#grpc.metrics.client) + + * [**grpc.metrics.server** - `grpcstarter.extensions.metrics.GrpcMetricsProperties$Server`](#grpc.metrics.server) +* [**grpc-test**](#grpc-test) + * [**grpc.test** - `grpcstarter.extensions.test.GrpcTestProperties`](#grpc.test) + + * [**grpc.test.server** - `grpcstarter.extensions.test.GrpcTestProperties$Server`](#grpc.test.server) +* [**grpc-tracing**](#grpc-tracing) + * [**grpc.tracing** - `grpcstarter.extensions.tracing.GrpcTracingProperties`](#grpc.tracing) + + * [**grpc.tracing.client** - `grpcstarter.extensions.tracing.GrpcTracingProperties$Client`](#grpc.tracing.client) + + * [**grpc.tracing.server** - `grpcstarter.extensions.tracing.GrpcTracingProperties$Server`](#grpc.tracing.server) +* [**grpc-transcoding**](#grpc-transcoding) + * [**grpc.transcoding** - `grpcstarter.extensions.transcoding.GrpcTranscodingProperties`](#grpc.transcoding) +* [**grpc-validation**](#grpc-validation) + * [**grpc.validation** - `grpcstarter.extensions.validation.GrpcValidationProperties`](#grpc.validation) + + * [**grpc.validation.client** - `grpcstarter.extensions.validation.GrpcValidationProperties$Client`](#grpc.validation.client) + + * [**grpc.validation.server** - `grpcstarter.extensions.validation.GrpcValidationProperties$Server`](#grpc.validation.server) + +## grpc-client-boot-autoconfigure +### grpc.client.tls.key-manager +**Class:** `grpcstarter.client.GrpcClientProperties$Tls$KeyManager` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| cert-chain| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getCertificateChain()| | | +| private-key| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getPrivateKey()| | | +| private-key-password| java.lang.String| @see TlsChannelCredentials.Builder#getPrivateKeyPassword()| | | +### grpc.client.tls.trust-manager +**Class:** `grpcstarter.client.GrpcClientProperties$Tls$TrustManager` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| root-certs| org.springframework.core.io.Resource| @see TlsChannelCredentials.Builder#getRootCertificates()| | | +### grpc.client +**Class:** `grpcstarter.client.GrpcClientProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| authority| java.lang.String| Default authority. <p> e.g. localhost:8080 </p>| | | +| base-packages| java.util.List<java.lang.String>| Base packages to scan for gRPC stubs. <p> This value will merge with \{@link EnableGrpcClients#basePackages}, only takes effect if \{@link EnableGrpcClients#basePackages} is not set. </p> <p> The advantage of using configuration is no need to introduce external annotations. </p>| | | +| channels| java.util.List<grpcstarter.client.GrpcClientProperties$Channel>| Channels configuration.| | | +| compression| java.lang.String| Compression configuration. @see AbstractStub#withCompression(String)| | | +| deadline| java.lang.Long| Deadline after in milliseconds, default value is 5000. @see AbstractStub#withDeadline(Deadline) @since 3.2.0| | | +| enabled| java.lang.Boolean| Whether to enable gRPC client autoconfiguration, default true.| true| | +| max-inbound-message-size| org.springframework.util.unit.DataSize| Default max inbound message size, default value is 4MB. @see DataSize @see GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE| | | +| max-inbound-metadata-size| org.springframework.util.unit.DataSize| Default max metadata size, default value is 8KB. @see DataSize @see GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE| | | +| max-outbound-message-size| org.springframework.util.unit.DataSize| Default max outbound message size. @see DataSize @see AbstractStub#withMaxOutboundMessageSize(int)| | | +| metadata| java.util.List<grpcstarter.client.GrpcClientProperties$Metadata>| Default metadata will be added to all the gRPC requests.| | | +| shutdown-timeout| java.lang.Long| Channel shutdown timeout in milliseconds, default value is 5000.| 5000| | +| warn-unused-config-enabled| java.lang.Boolean| Whether to enable warn unused config, default true.| true| | +### grpc.client.in-process +**Class:** `grpcstarter.client.GrpcClientProperties$InProcess` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| name| java.lang.String| In-process client name. <p> If set, will create an in-process channel by default, usually for testing. </p>| | | +### grpc.client.refresh +**Class:** `grpcstarter.client.GrpcClientProperties$Refresh` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable refresh grpc clients, default false. <p> NOTE: this feature needs 'spring-cloud-context' dependency in the classpath. </p>| false| | +### grpc.client.retry +**Class:** `grpcstarter.client.GrpcClientProperties$Retry` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable retry. @see io.grpc.ManagedChannelBuilder#enableRetry() @see io.grpc.ManagedChannelBuilder#disableRetry()| | | +| max-retry-attempts| java.lang.Integer| Maximum number of attempts to retry. @see io.grpc.ManagedChannelBuilder#maxRetryAttempts(int)| | | +| per-rpc-buffer-limit| org.springframework.util.unit.DataSize| The maximum number of retry buffer entries per RPC. @see io.grpc.ManagedChannelBuilder#perRpcBufferLimit(long)| | | +| retry-buffer-size| org.springframework.util.unit.DataSize| The maximum number of retry buffer entries. @see io.grpc.ManagedChannelBuilder#retryBufferSize(long)| | | +### grpc.client.tls +**Class:** `grpcstarter.client.GrpcClientProperties$Tls` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| + +## grpc-server-boot-autoconfigure +### grpc.server.tls.key-manager +**Class:** `grpcstarter.server.GrpcServerProperties$Tls$KeyManager` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| cert-chain| org.springframework.core.io.Resource| @see TlsServerCredentials.Builder#getCertificateChain()| | | +| private-key| org.springframework.core.io.Resource| @see TlsServerCredentials.Builder#getPrivateKey()| | | +| private-key-password| java.lang.String| @see TlsServerCredentials.Builder#getPrivateKeyPassword()| | | +### grpc.server.tls.trust-manager +**Class:** `grpcstarter.server.GrpcServerProperties$Tls$TrustManager` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| root-certs| org.springframework.core.io.Resource| @see TlsServerCredentials.Builder#getRootCertificates()| | | +### grpc.server.health.datasource +**Class:** `grpcstarter.server.GrpcServerProperties$Health$DataSource` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable datasource health check, default true.| true| | +| service| java.lang.String| The service name that will be used for datasource health check, default value is 'datasource'.| datasource| | +| timeout| java.lang.Integer| \{@link #validationQuery} timeout, unit seconds.| | | +| validation-query| java.lang.String| The SQL query that will be used to validate datasource connection, default value is 'SELECT 1'.| SELECT 1| | +### grpc.server.health.redis +**Class:** `grpcstarter.server.GrpcServerProperties$Health$Redis` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable redis health check, default true.| true| | +| service| java.lang.String| The service name that will be used for redis health check, default value is 'redis'.| redis| | +### grpc.server +**Class:** `grpcstarter.server.GrpcServerProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enable-empty-server| java.lang.Boolean| Whether to start a gRPC server when no service found, default true.| true| | +| enabled| java.lang.Boolean| Whether to enable gRPC server autoconfiguration, default true.| true| | +| max-inbound-message-size| org.springframework.util.unit.DataSize| The maximum message size allowed to be received on the server, default 4MB. @see GrpcUtil#DEFAULT_MAX_MESSAGE_SIZE| | | +| max-inbound-metadata-size| org.springframework.util.unit.DataSize| The maximum size of metadata allowed to be received, default 8KB. @see GrpcUtil#DEFAULT_MAX_HEADER_LIST_SIZE| | | +| port| java.lang.Integer| gRPC server port, default 9090, 0 or negative numbers will use random port.| 9090| | +| shutdown-timeout| java.lang.Long| Graceful shutdown timeout, default 30s, if 0 will wait forever util all active calls finished.| 30000| | +### grpc.server.channelz +**Class:** `grpcstarter.server.GrpcServerProperties$Channelz` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to register \{@link ChannelzService}, default false.| false| | +| max-page-size| java.lang.Integer| The maximum page size to return, default 100. @see AdminInterface| 100| | +### grpc.server.exception-handling +**Class:** `grpcstarter.server.GrpcServerProperties$ExceptionHandling` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| default-exception-advice-enabled| java.lang.Boolean| Whether to enable \{@link DefaultGrpcExceptionAdvice}, default true. <p> \{@link DefaultGrpcExceptionAdvice} will handle exceptions recognized by gRPC, including: </p> <ul> <li>\{@link StatusRuntimeException}</li> <li>\{@link StatusException}</li> </ul> <p> When enabled, you can directly throw \{@link StatusRuntimeException} or \{@link StatusException} in service implementation, and the exception will be handled by \{@link DefaultGrpcExceptionAdvice}. </p> <pre>\{@code @GrpcService public class SimpleService extends SimpleServiceGrpc.SimpleServiceImplBase \{ @Override public void unaryRpc(SimpleRequest request, StreamObserver<SimpleResponse> responseObserver) \{ throw new StatusRuntimeException(Status.INVALID_ARGUMENT.withDescription("Invalid request")); } } }</pre> @see DefaultGrpcExceptionAdvice @since 3.2.3| true| | +| enabled| java.lang.Boolean| Whether to enable exception handling, default true.| true| | +### grpc.server.health +**Class:** `grpcstarter.server.GrpcServerProperties$Health` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable health check, default false.| true| | +### grpc.server.in-process +**Class:** `grpcstarter.server.GrpcServerProperties$InProcess` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| name| java.lang.String| In-process server name, if configured, will create an in-process server, usually for testing.| | | +### grpc.server.reflection +**Class:** `grpcstarter.server.GrpcServerProperties$Reflection` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to register reflection service, default false.| false| | +### grpc.server.response +**Class:** `grpcstarter.server.GrpcServerProperties$Response` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| max-description-length| java.lang.Integer| The maximum length of response description. <p> When the length of the description exceeds this value, it will be truncated. </p> @since 3.2.3| 2048| | +### grpc.server.tls +**Class:** `grpcstarter.server.GrpcServerProperties$Tls` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| + +## grpc-metrics +### grpc.metrics +**Class:** `grpcstarter.extensions.metrics.GrpcMetricsProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable metrics, default is \{@code true}| true| | +### grpc.metrics.client +**Class:** `grpcstarter.extensions.metrics.GrpcMetricsProperties$Client` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable client metrics, default is \{@code true}| true| | +| order| java.lang.Integer| The order of the client metrics interceptor. Default is \{@code 0}.| 0| | +### grpc.metrics.server +**Class:** `grpcstarter.extensions.metrics.GrpcMetricsProperties$Server` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable server metrics, default is \{@code true}| true| | +| order| java.lang.Integer| The order of the server metrics interceptor. Default is \{@code 0}.| 0| | + +## grpc-test +### grpc.test +**Class:** `grpcstarter.extensions.test.GrpcTestProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable test, default is \{@code true}.| true| | +### grpc.test.server +**Class:** `grpcstarter.extensions.test.GrpcTestProperties$Server` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable test, default is \{@code true}.| true| | +| port-type| grpcstarter.extensions.test.GrpcTestProperties$PortType| Port configuration, default is \{@link PortType#IN_PROCESS}, which means start grpc server with in-process transport. @see PortType| | | + +## grpc-tracing +### grpc.tracing +**Class:** `grpcstarter.extensions.tracing.GrpcTracingProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable tracing, default is \{@code true}| true| | +### grpc.tracing.client +**Class:** `grpcstarter.extensions.tracing.GrpcTracingProperties$Client` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable client tracing, default is \{@code true}| true| | +| order| java.lang.Integer| The order of the client tracing interceptor. Default is \{@code 0}.| 0| | +### grpc.tracing.server +**Class:** `grpcstarter.extensions.tracing.GrpcTracingProperties$Server` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| whether to enable server tracing, default is \{@code true}| true| | +| order| java.lang.Integer| The order of the server tracing interceptor. Default is \{@code 0}.| 0| | + +## grpc-transcoding +### grpc.transcoding +**Class:** `grpcstarter.extensions.transcoding.GrpcTranscodingProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable transcoding auto-configuration, default \{@code true}.| true| | +| endpoint| java.lang.String| gRPC server endpoint, if not set, will use \{@code localhost:$\{grpc.server.port}}.| | | + +## grpc-validation +### grpc.validation +**Class:** `grpcstarter.extensions.validation.GrpcValidationProperties` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| backend| grpcstarter.extensions.validation.GrpcValidationProperties$Backend| Validation implementation.| | | +| enabled| java.lang.Boolean| Whether to enable validation, default is \{@code true}.| true| | +### grpc.validation.client +**Class:** `grpcstarter.extensions.validation.GrpcValidationProperties$Client` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable validation, default is \{@code true}.| true| | +| order| java.lang.Integer| Validating interceptor order, default is \{@code 0}.| 0| | +### grpc.validation.server +**Class:** `grpcstarter.extensions.validation.GrpcValidationProperties$Server` + +|Key|Type|Description|Default value|Deprecation| +|---|----|-----------|-------------|-----------| +| enabled| java.lang.Boolean| Whether to enable validation, default is \{@code true}.| true| | +| order| java.lang.Integer| Validating interceptor order, default is \{@code 0}.| 0| | + +This is a generated file, generated at: **2024-06-11T01:05:18.345117** diff --git a/website/docs/40-version.md b/website/docs/50-version.md similarity index 97% rename from website/docs/40-version.md rename to website/docs/50-version.md index 1cb459dd..a51e830e 100644 --- a/website/docs/40-version.md +++ b/website/docs/50-version.md @@ -1,5 +1,5 @@ --- -sidebar_position: 40 +sidebar_position: 50 --- # Version Matrix