Improve channel factory API
This commit improves the GrpcChannelFactory createChannel API by introducing `ChannelBuilderOptions` that can be specified during channel creation. Additionally, concrete Netty channel factory implementations have been added as well as adding type to the GrpcChannelBuilderCustomizer which helps match customizers to channel factories.
This commit is contained in:
@@ -16,12 +16,10 @@ To bind to this service on a local server:
|
||||
----
|
||||
@Bean
|
||||
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
|
||||
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090").build());
|
||||
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090"));
|
||||
}
|
||||
----
|
||||
|
||||
The `GrpcChannelFactory` creates a `ChannelBuilder` that you can customize before building the channel if necessary.
|
||||
|
||||
=== Shaded Netty Client
|
||||
|
||||
The default client implementation uses the Netty client.
|
||||
@@ -61,7 +59,53 @@ dependencies {
|
||||
----
|
||||
|
||||
== Channel Configuration
|
||||
The channel factory provides an API to create channels.
|
||||
The channel creation process can be configured as follows.
|
||||
|
||||
=== Channel Builder Customizer
|
||||
The `ManagedChannelBuilder` used by the factory to create the channel can be customized prior to channel creation.
|
||||
|
||||
==== Global
|
||||
To customize the builder used for all created channels you can register one more `GrpcChannelBuilderCustomizer` beans.
|
||||
The customizers are applied to the auto-configured `GrpcChannelFactory` in order according to their bean natural ordering (i.e. `@Order`).
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
@Order(100)
|
||||
GrpcChannelBuilderCustomizer<NettyChannelBuilder> flowControlCustomizer() {
|
||||
return (name, builder) -> builder.flowControlWindow(1024 * 1024);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(200)
|
||||
<T extends ManagedChannelBuilder<T>> GrpcChannelBuilderCustomizer<T> retryChannelCustomizer() {
|
||||
return (name, builder) -> builder.enableRetry().maxRetryAttempts(5);
|
||||
}
|
||||
----
|
||||
|
||||
In the preceding example, the `flowControlCustomizer` customizer is applied prior to the `retryChannelCustomizer`.
|
||||
Furthermore, the `flowControlCustomizer` is only applied if the auto-configured channel factory is a `NettyGrpcChannelFactory`.
|
||||
|
||||
==== Per-channel
|
||||
To customize an individual channel you can specify a `GrpcChannelBuilderCustomizer` on the options passed to the factory during channel creation.
|
||||
The per-channel customizer will be applied after any global customizers.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channelFactory) {
|
||||
ChannelBuilderOptions options = ChannelBuilderOptions.defaults()
|
||||
.withCustomizer((__, b) -> b.disableRetry());
|
||||
ManagedChannel channel = channelFactory.createChannel("localhost", options);
|
||||
return SimpleGrpc.newBlockingStub(channel);
|
||||
}
|
||||
----
|
||||
The above example disables retries for the single created channel only.
|
||||
|
||||
WARNING: While the channel builder customizer gives you full access to the native channel builder, you should not call `build` on the customized builder as the channel factory handles the `build` call for you and doing so will create orphaned channels.
|
||||
|
||||
=== Application Properties
|
||||
The default `GrpcChannelFactory` implementation can also create a "named" channel, which you can then use to extract the configuration to connect to the server.
|
||||
For example:
|
||||
|
||||
@@ -69,7 +113,7 @@ For example:
|
||||
----
|
||||
@Bean
|
||||
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
|
||||
return SimpleGrpc.newBlockingStub(channels.createChannel("local").build());
|
||||
return SimpleGrpc.newBlockingStub(channels.createChannel("local"));
|
||||
}
|
||||
----
|
||||
|
||||
@@ -82,9 +126,6 @@ spring.grpc.client.channels.local.address=0.0.0.0:9090
|
||||
|
||||
There is a default named channel that you can configure as `spring.grpc.client.default-channel.*`, and then it will be used by default if there is no channel with the name specified in the channel creation.
|
||||
|
||||
Beans of type `GrpcChannelBuilderCustomizer` can be used to customize the `ChannelBuilder` before the channel is built.
|
||||
This can be useful for setting up security, for example.
|
||||
|
||||
== The Local Server Port
|
||||
|
||||
If you are running a gRPC server locally as part of your application, you will often want to connect to it in an integration test.
|
||||
@@ -106,27 +147,52 @@ SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort i
|
||||
|
||||
=== Global
|
||||
To add a client interceptor to be applied to all created channels you can simply register a client interceptor bean and then annotate it with `@GlobalClientInterceptor`.
|
||||
The interceptors are ordered according to their bean natural ordering (i.e. `@Order`).
|
||||
When you register multiple interceptor beans they are ordered according to their bean natural ordering (i.e. `@Order`).
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
@Order(100)
|
||||
@GlobalClientInterceptor
|
||||
ClientInterceptor myGlobalLoggingInterceptor() {
|
||||
return new MyLoggingInterceptor();
|
||||
ClientInterceptor globalLoggingInterceptor() {
|
||||
return new LoggingInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Order(200)
|
||||
@GlobalClientInterceptor
|
||||
ClientInterceptor globalExtraThingsInterceptor() {
|
||||
return new ExtraThingsInterceptor();
|
||||
}
|
||||
----
|
||||
|
||||
=== Per-Channel
|
||||
To add one or more client interceptors to be applied to a single client channel you can simply pass in the interceptor instance(s) when invoking the channel factory to create the channel.
|
||||
In the preceding example, the `globalLoggingInterceptor` customizer is applied prior to the `globalExtraThingsInterceptor`.
|
||||
|
||||
=== Per-Channel
|
||||
To add one or more client interceptors to be applied to a single client channel you can simply set the interceptor instance(s) on the options passed to the channel factory when creating the channel.
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@Bean
|
||||
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channelFactory) {
|
||||
ClientInterceptor interceptor1 = getChannelInterceptor1();
|
||||
ClientInterceptor interceptor2 = getChannelInterceptor2();
|
||||
ChannelBuilderOptions options = ChannelBuilderOptions.defaults()
|
||||
.withInterceptors(List.of(interceptor1, interceptor2));
|
||||
ManagedChannel channel = channelFactory.createChannel("localhost", options);
|
||||
return SimpleGrpc.newBlockingStub(channel);
|
||||
}
|
||||
----
|
||||
The above example applies `interceptor1` then `interceptor2` to the single created channel.
|
||||
|
||||
WARNING: While the channel builder customizer gives you full access to the native channel builder, we recommend not calling `intercept` on the customized builder but rather set the per-channel interceptors using the `ChannelBuilderOptions` as described above.
|
||||
If you do call `intercept` directly on the builder then those interceptors will be applied before the above described `global` and `per-channel` interceptors.
|
||||
|
||||
The interceptors are ordered according to their position in the specified list.
|
||||
|
||||
=== Blended
|
||||
When a channel is constructed with both global and per-client interceptors, the global interceptors are first applied in their sorted order followed by the per-service interceptors in their sorted order.
|
||||
When a channel is constructed with both global and per-channel interceptors, the global interceptors are first applied in their sorted order followed by the per-channel interceptors in their sorted order.
|
||||
|
||||
However, by setting the `mergeWithGlobalInterceptors` parameter on the channel factory to `"true"` you can change this behavior so that the interceptors are all combined and then sorted according to their bean natural ordering (i.e. `@Order` or `Ordered` interface).
|
||||
However, by setting the `withInterceptorsMerge` parameter on the `ChannelBuilderOptions` passed to the channel factory to `"true"` you can change this behavior so that the interceptors are all combined and then sorted according to their bean natural ordering (i.e. `@Order` or `Ordered` interface).
|
||||
|
||||
You can use this option if you want to add a per-client interceptor between global interceptors.
|
||||
|
||||
|
||||
@@ -2,48 +2,48 @@
|
||||
|Name | Default | Description
|
||||
|
||||
|spring.grpc.client.channels | |
|
||||
|spring.grpc.client.default-channel.address | | The target address uri to connect to.
|
||||
|spring.grpc.client.default-channel.default-load-balancing-policy | | The default load balancing policy the channel should use.
|
||||
|spring.grpc.client.default-channel.enable-keep-alive | | Whether keep alive is enabled on the channel.
|
||||
|spring.grpc.client.default-channel.health.enabled | | Whether to enable client-side health check for the channel.
|
||||
|spring.grpc.client.default-channel.address | `+++static://localhost:9090+++` | The target address uri to connect to.
|
||||
|spring.grpc.client.default-channel.default-load-balancing-policy | `+++round_robin+++` | The default load balancing policy the channel should use.
|
||||
|spring.grpc.client.default-channel.enable-keep-alive | `+++false+++` | Whether keep alive is enabled on the channel.
|
||||
|spring.grpc.client.default-channel.health.enabled | `+++false+++` | Whether to enable client-side health check for the channel.
|
||||
|spring.grpc.client.default-channel.health.service-name | | Name of the service to check health on.
|
||||
|spring.grpc.client.default-channel.idle-timeout | | The duration without ongoing RPCs before going to idle mode.
|
||||
|spring.grpc.client.default-channel.keep-alive-time | | The delay before sending a keepAlive. Note that shorter intervals increase the network burden for the server and this value can not be lower than 'permitKeepAliveTime' on the server.
|
||||
|spring.grpc.client.default-channel.keep-alive-timeout | | The default timeout for a keepAlives ping request.
|
||||
|spring.grpc.client.default-channel.keep-alive-without-calls | | Whether a keepAlive will be performed when there are no outstanding RPC on a connection.
|
||||
|spring.grpc.client.default-channel.max-inbound-message-size | | Maximum message size allowed to be received by the channel (default 4MiB). Set to '-1' to use the highest possible limit (not recommended).
|
||||
|spring.grpc.client.default-channel.max-inbound-metadata-size | | Maximum metadata size allowed to be received by the channel (default 8KiB). Set to '-1' to use the highest possible limit (not recommended).
|
||||
|spring.grpc.client.default-channel.negotiation-type | | The negotiation type for the channel.
|
||||
|spring.grpc.client.default-channel.secure | | Flag to say that strict SSL checks are not enabled (so the remote certificate could be anonymous).
|
||||
|spring.grpc.client.default-channel.idle-timeout | `+++20s+++` | The duration without ongoing RPCs before going to idle mode.
|
||||
|spring.grpc.client.default-channel.keep-alive-time | `+++5m+++` | The delay before sending a keepAlive. Note that shorter intervals increase the network burden for the server and this value can not be lower than 'permitKeepAliveTime' on the server.
|
||||
|spring.grpc.client.default-channel.keep-alive-timeout | `+++20s+++` | The default timeout for a keepAlives ping request.
|
||||
|spring.grpc.client.default-channel.keep-alive-without-calls | `+++false+++` | Whether a keepAlive will be performed when there are no outstanding RPC on a connection.
|
||||
|spring.grpc.client.default-channel.max-inbound-message-size | `+++4194304B+++` | Maximum message size allowed to be received by the channel (default 4MiB). Set to '-1' to use the highest possible limit (not recommended).
|
||||
|spring.grpc.client.default-channel.max-inbound-metadata-size | `+++8192B+++` | Maximum metadata size allowed to be received by the channel (default 8KiB). Set to '-1' to use the highest possible limit (not recommended).
|
||||
|spring.grpc.client.default-channel.negotiation-type | `+++plaintext+++` | The negotiation type for the channel.
|
||||
|spring.grpc.client.default-channel.secure | `+++true+++` | Flag to say that strict SSL checks are not enabled (so the remote certificate could be anonymous).
|
||||
|spring.grpc.client.default-channel.ssl.bundle | | SSL bundle name.
|
||||
|spring.grpc.client.default-channel.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.
|
||||
|spring.grpc.client.default-channel.user-agent | | The custom User-Agent for the channel.
|
||||
|spring.grpc.client.observations.enabled | `+++true+++` | Whether to enable Observations on the client.
|
||||
|spring.grpc.server.address | | The address to bind to. could be a host:port combination or a pseudo URL like static://host:port. Can not be set if host or port are set independently.
|
||||
|spring.grpc.server.exception-handling.enabled | `+++true+++` | Whether to enable user-defined global exception handling on the gRPC server.
|
||||
|spring.grpc.server.health.actuator.enabled | | Whether to adapt Actuator health indicators into gRPC health checks.
|
||||
|spring.grpc.server.health.actuator.enabled | `+++true+++` | Whether to adapt Actuator health indicators into gRPC health checks.
|
||||
|spring.grpc.server.health.actuator.health-indicator-paths | | List of Actuator health indicator paths to adapt into gRPC health checks.
|
||||
|spring.grpc.server.health.actuator.update-initial-delay | | The initial delay before updating the health status the very first time.
|
||||
|spring.grpc.server.health.actuator.update-overall-health | | Whether to update the overall gRPC server health (the '' service) with the aggregate status of the configured health indicators.
|
||||
|spring.grpc.server.health.actuator.update-rate | | How often to update the health status.
|
||||
|spring.grpc.server.health.enabled | | Whether to auto-configure Health feature on the gRPC server.
|
||||
|spring.grpc.server.host | | Server address to bind to. The default is any IP address ('*').
|
||||
|spring.grpc.server.health.actuator.update-initial-delay | `+++5s+++` | The initial delay before updating the health status the very first time.
|
||||
|spring.grpc.server.health.actuator.update-overall-health | `+++true+++` | Whether to update the overall gRPC server health (the '' service) with the aggregate status of the configured health indicators.
|
||||
|spring.grpc.server.health.actuator.update-rate | `+++5s+++` | How often to update the health status.
|
||||
|spring.grpc.server.health.enabled | `+++true+++` | Whether to auto-configure Health feature on the gRPC server.
|
||||
|spring.grpc.server.host | `+++*+++` | Server address to bind to. The default is any IP address ('*').
|
||||
|spring.grpc.server.keep-alive.max-age | | Maximum time a connection may exist before being gracefully terminated (default infinite).
|
||||
|spring.grpc.server.keep-alive.max-age-grace | | Maximum time for graceful connection termination (default infinite).
|
||||
|spring.grpc.server.keep-alive.max-idle | | Maximum time a connection can remain idle before being gracefully terminated (default infinite).
|
||||
|spring.grpc.server.keep-alive.permit-time | | Maximum keep-alive time clients are permitted to configure (default 5m).
|
||||
|spring.grpc.server.keep-alive.permit-without-calls | | Whether clients are permitted to send keep alive pings when there are no outstanding RPCs on the connection (default false).
|
||||
|spring.grpc.server.keep-alive.time | | Duration without read activity before sending a keep alive ping (default 2h).
|
||||
|spring.grpc.server.keep-alive.timeout | | Maximum time to wait for read activity after sending a keep alive ping. If sender does not receive an acknowledgment within this time, it will close the connection (default 20s).
|
||||
|spring.grpc.server.max-inbound-message-size | | Maximum message size allowed to be received by the server (default 4MiB).
|
||||
|spring.grpc.server.max-inbound-metadata-size | | Maximum metadata size allowed to be received by the server (default 8KiB).
|
||||
|spring.grpc.server.keep-alive.permit-time | `+++5m+++` | Maximum keep-alive time clients are permitted to configure (default 5m).
|
||||
|spring.grpc.server.keep-alive.permit-without-calls | `+++false+++` | Whether clients are permitted to send keep alive pings when there are no outstanding RPCs on the connection (default false).
|
||||
|spring.grpc.server.keep-alive.time | `+++2h+++` | Duration without read activity before sending a keep alive ping (default 2h).
|
||||
|spring.grpc.server.keep-alive.timeout | `+++20s+++` | Maximum time to wait for read activity after sending a keep alive ping. If sender does not receive an acknowledgment within this time, it will close the connection (default 20s).
|
||||
|spring.grpc.server.max-inbound-message-size | `+++4194304B+++` | Maximum message size allowed to be received by the server (default 4MiB).
|
||||
|spring.grpc.server.max-inbound-metadata-size | `+++8192B+++` | Maximum metadata size allowed to be received by the server (default 8KiB).
|
||||
|spring.grpc.server.observations.enabled | `+++true+++` | Whether to enable Observations on the server.
|
||||
|spring.grpc.server.port | `+++9090+++` | Server port to listen on. When the value is 0, a random available port is selected. The default is 9090.
|
||||
|spring.grpc.server.reflection.enabled | `+++true+++` | Whether to enable Reflection on the gRPC server.
|
||||
|spring.grpc.server.shutdown-grace-period | | Maximum time to wait for the server to gracefully shutdown. When the value is negative, the server waits forever. When the value is 0, the server will force shutdown immediately. The default is 30 seconds.
|
||||
|spring.grpc.server.shutdown-grace-period | `+++30s+++` | Maximum time to wait for the server to gracefully shutdown. When the value is negative, the server waits forever. When the value is 0, the server will force shutdown immediately. The default is 30 seconds.
|
||||
|spring.grpc.server.ssl.bundle | | SSL bundle name.
|
||||
|spring.grpc.server.ssl.client-auth | | Client authentication mode.
|
||||
|spring.grpc.server.ssl.client-auth | `+++none+++` | Client authentication mode.
|
||||
|spring.grpc.server.ssl.enabled | | Whether to enable SSL support. Enabled automatically if "bundle" is provided unless specified otherwise.
|
||||
|spring.grpc.server.ssl.secure | | Flag to indicate that client authentication is secure (i.e. certificates are checked). Do not set this to false in production.
|
||||
|spring.grpc.server.ssl.secure | `+++true+++` | Flag to indicate that client authentication is secure (i.e. certificates are checked). Do not set this to false in production.
|
||||
|
||||
|===
|
||||
Reference in New Issue
Block a user