Skip to content

Commit 946c013

Browse files
committed
Add docs for channel factory
1 parent d52f7c2 commit 946c013

File tree

1 file changed

+80
-14
lines changed
  • spring-grpc-docs/src/main/antora/modules/ROOT/pages

1 file changed

+80
-14
lines changed

spring-grpc-docs/src/main/antora/modules/ROOT/pages/client.adoc

Lines changed: 80 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ To bind to this service on a local server:
1616
----
1717
@Bean
1818
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
19-
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090").build());
19+
return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090"));
2020
}
2121
----
2222

23-
The `GrpcChannelFactory` creates a `ChannelBuilder` that you can customize before building the channel if necessary.
24-
2523
=== Shaded Netty Client
2624

2725
The default client implementation uses the Netty client.
@@ -61,15 +59,61 @@ dependencies {
6159
----
6260

6361
== Channel Configuration
62+
The channel factory provides an API to create channels.
63+
The channel creation process can be configured as follows.
64+
65+
=== Channel Builder Customizer
66+
The `ManagedChannelBuilder` used by the factory to create the channel can be customized prior to channel creation.
67+
68+
==== Global
69+
To customize the builder used for all created channels you can register one more `GrpcChannelBuilderCustomizer` beans.
70+
The customizers are applied to the auto-configured `GrpcChannelFactory` in order according to their bean natural ordering (i.e. `@Order`).
71+
72+
[source,java]
73+
----
74+
@Bean
75+
@Order(100)
76+
GrpcChannelBuilderCustomizer<NettyChannelBuilder> flowControlCustomizer() {
77+
return (name, builder) -> builder.flowControlWindow(1024 * 1024);
78+
}
6479
80+
@Bean
81+
@Order(200)
82+
<T extends ManagedChannelBuilder<T>> GrpcChannelBuilderCustomizer<T> retryChannelCustomizer() {
83+
return (name, builder) -> builder.enableRetry().maxRetryAttempts(5);
84+
}
85+
----
86+
87+
In the preceding example, the `flowControlCustomizer` customizer is applied prior to the `retryChannelCustomizer`.
88+
Furthermore, the `flowControlCustomizer` is only applied if the auto-configured channel factory is a `NettyGrpcChannelFactory`.
89+
90+
==== Per-channel
91+
To customize an individual channel you can specify a `GrpcChannelBuilderCustomizer` on the options passed to the factory during channel creation.
92+
The per-channel customizer will be applied after any global customizers.
93+
94+
[source,java]
95+
----
96+
@Bean
97+
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channelFactory) {
98+
ChannelBuilderOptions options = ChannelBuilderOptions.defaults()
99+
.withCustomizer((__, b) -> b.disableRetry());
100+
ManagedChannel channel = channelFactory.createChannel("localhost", options);
101+
return SimpleGrpc.newBlockingStub(channel);
102+
}
103+
----
104+
The above example disables retries for the single created channel only.
105+
106+
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.
107+
108+
=== Application Properties
65109
The default `GrpcChannelFactory` implementation can also create a "named" channel, which you can then use to extract the configuration to connect to the server.
66110
For example:
67111

68112
[source,java]
69113
----
70114
@Bean
71115
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) {
72-
return SimpleGrpc.newBlockingStub(channels.createChannel("local").build());
116+
return SimpleGrpc.newBlockingStub(channels.createChannel("local"));
73117
}
74118
----
75119

@@ -82,9 +126,6 @@ spring.grpc.client.channels.local.address=0.0.0.0:9090
82126

83127
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.
84128

85-
Beans of type `GrpcChannelBuilderCustomizer` can be used to customize the `ChannelBuilder` before the channel is built.
86-
This can be useful for setting up security, for example.
87-
88129
== The Local Server Port
89130

90131
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
106147

107148
=== Global
108149
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`.
109-
The interceptors are ordered according to their bean natural ordering (i.e. `@Order`).
150+
When you register multiple interceptor beans they are ordered according to their bean natural ordering (i.e. `@Order`).
110151

111152
[source,java]
112153
----
113154
@Bean
114155
@Order(100)
115156
@GlobalClientInterceptor
116-
ClientInterceptor myGlobalLoggingInterceptor() {
117-
return new MyLoggingInterceptor();
157+
ClientInterceptor globalLoggingInterceptor() {
158+
return new LoggingInterceptor();
159+
}
160+
161+
@Bean
162+
@Order(200)
163+
@GlobalClientInterceptor
164+
ClientInterceptor globalExtraThingsInterceptor() {
165+
return new ExtraThingsInterceptor();
118166
}
119167
----
120168

169+
In the preceding example, the `globalLoggingInterceptor` customizer is applied prior to the `globalExtraThingsInterceptor`.
170+
121171
=== Per-Channel
122-
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.
172+
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.
173+
174+
[source,java]
175+
----
176+
@Bean
177+
SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channelFactory) {
178+
ClientInterceptor interceptor1 = getChannelInterceptor1();
179+
ClientInterceptor interceptor2 = getChannelInterceptor2();
180+
ChannelBuilderOptions options = ChannelBuilderOptions.defaults()
181+
.withInterceptors(List.of(interceptor1, interceptor2));
182+
ManagedChannel channel = channelFactory.createChannel("localhost", options);
183+
return SimpleGrpc.newBlockingStub(channel);
184+
}
185+
----
186+
The above example applies `interceptor1` then `interceptor2` to the single created channel.
187+
188+
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.
189+
If you do call `intercept` directly on the builder then those interceptors will be applied before the above described `global` and `per-channel` interceptors.
123190

124-
The interceptors are ordered according to their position in the specified list.
125191

126192
=== Blended
127-
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.
193+
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.
128194

129-
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).
195+
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).
130196

131197
You can use this option if you want to add a per-client interceptor between global interceptors.
132198

0 commit comments

Comments
 (0)