1
1
///////////////////////////////////////////////////////////////////////////////
2
2
3
- Copyright (c) 2019, 2023 Oracle and/or its affiliates.
3
+ Copyright (c) 2019, 2024 Oracle and/or its affiliates.
4
4
5
5
Licensed under the Apache License, Version 2.0 (the "License");
6
6
you may not use this file except in compliance with the License.
@@ -27,10 +27,173 @@ include::{rootdir}/includes/se.adoc[]
27
27
== Contents
28
28
29
29
- <<Overview, Overview>>
30
+ - <<Maven Coordinates, Maven Coordinates>>
31
+ - <<Usage, Usage>>
32
+ ** <<Generated Stubs, Generated Stubs>>
33
+ ** <<Service Descriptors, Service Descriptors>>
34
+ ** <<Client URI Suppliers, Client URI Suppliers>>
35
+ ** <<gRPC Interceptors, gRPC Interceptors>>
36
+ - <<Configuration, Configuration>>
30
37
31
38
== Overview
32
39
33
- gRPC client is temporarily removed from Helidon, please follow issue
34
- https://github.com/helidon-io/helidon/issues/5418
40
+ The Helidon gRPC client API is part of the WebClient API, but with specific support to
41
+ invoke remote procedures and to register handlers for responses. All four types of gRPC
42
+ calls are supported: unary, bi-directional, client stream and server stream. A
43
+ Helidon gRPC client can be configured either using generated stubs (the most popular
44
+ option) or using manually crafted service descriptors.
45
+
46
+ include::{rootdir}/includes/dependencies.adoc[]
47
+
48
+ [source,xml]
49
+ ----
50
+ <dependency>
51
+ <groupId>io.helidon.webclient</groupId>
52
+ <artifactId>helidon-webclient-grpc</artifactId>
53
+ </dependency>
54
+ ----
55
+
56
+ == Usage
57
+
58
+ === Generated Stubs
59
+
60
+ A Helidon gRPC client can be configured from generated protobuf stubs. In what follows,
61
+ we shall use the following proto file and the corresponding stubs generated using
62
+ the `protoc` command:
63
+
64
+ [source, proto]
65
+ ----
66
+ syntax = "proto3";
67
+ option java_package = "my.package";
68
+
69
+ service StringService {
70
+ rpc Upper (StringMessage) returns (StringMessage) {}
71
+ rpc Split (StringMessage) returns (stream StringMessage) {}
72
+ }
73
+
74
+ message StringMessage {
75
+ string text = 1;
76
+ }
77
+ ----
78
+
79
+ The gRPC protocol runs on top of HTTP/2, and as such requires TLS configuration to
80
+ establish a connection. Thus, the first step is to configure TLS as shown next:
81
+
82
+ [source,java]
83
+ ----
84
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_1, indent=0]
85
+ ----
86
+
87
+ After creating a `Tls` instance, a `WebClient` can be created as follows:
88
+
89
+ [source,java]
90
+ ----
91
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_2, indent=0]
92
+ ----
93
+
94
+ So far, this is all the same as for accessing any protected REST endpoint; the
95
+ next step is to obtain a gRPC client stub using our newly created client.
96
+ This can be accomplished by _switching_ the client protocol to gRPC, and
97
+ using its channel to create a stub:
98
+
99
+ [source,java]
100
+ ----
101
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_3, indent=0]
102
+ ----
103
+
104
+ Once a stub is created, it can be used to invoke any of its declared
105
+ methods, such as `upper` to uppercase a string:
106
+
107
+ [source,java]
108
+ ----
109
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_4, indent=0]
110
+ ----
111
+
112
+ When it comes to invoking a method that can return more than one value,
113
+ there are two options: it can block (we are using virtual theads after all!)
114
+ and return back an `Iterator` or you can provide a `StreamObserver` as it
115
+ is more commonly done when using gRPC. Let's consider the case of the
116
+ `split` method that breaks up a sentence into individual words, and
117
+ can thus return multiple string messages.
118
+
119
+ Using an iterator as a result:
120
+ [source,java]
121
+ ----
122
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_5, indent=0]
123
+ ----
124
+
125
+ Passing a stream observer and collecting all the messages into a `Future`
126
+ that returns an iterator:
127
+ [source,java]
128
+ ----
129
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_6, indent=0]
130
+ ----
131
+
132
+ === Service Descriptors
133
+
134
+ Service descriptors are an alternative to using generated stubs and the
135
+ `protoc` compiler. A service descriptor provides service meta-data to the
136
+ WebClient for the purpose of carrying out invocations. The descriptor
137
+ includes, the service name, and a description of each service method,
138
+ including its type, what it accepts and what it returns.
139
+
140
+ The following is a descriptor for a service that includes the methods
141
+ called in the previous section using a stub:
142
+ [source,java]
143
+ ----
144
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_7, indent=0]
145
+ ----
146
+
147
+ Configuring a `WebClient` with `Tls` is done in the same manner as shown
148
+ above for the stub case. Once the gRPC client is created, a service
149
+ descriptor can be provided, and a method invoked using the methods
150
+ `unary`, `clientStream`, `serverStream` or `bidi`. For example,
151
+
152
+ [source,java]
153
+ ----
154
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_8, indent=0]
155
+ ----
156
+
157
+ === Client URI Suppliers
158
+
159
+ A `ClientURISupplier` can be used to dynamically obtain a sequence of `ClientUri`
160
+ instances to access when executing a gRPC request. If a client URI supplier is
161
+ configured, the Helidon gRPC implementation will attempt to connect to each
162
+ endpoint one by one, in the order provided, until a connection is successfully
163
+ established. This feature is useful in certain environments in which more than one
164
+ identical server is available, but with some potentially unavailable or unreachable.
165
+
166
+ A few common implementations are provided in `ClientUriSuppliers`. These include
167
+ suppliers for strategies such as random, round-robin, among others. Applications
168
+ can either use one of the built-in suppliers or create their own.
169
+
170
+ The following example configures a round-robin supplier using a collection
171
+ of known servers:
172
+
173
+ [source,java]
174
+ ----
175
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_9, indent=0]
176
+ ----
177
+
178
+ If both a base URI and a client URI supplier are configured, the latter will
179
+ take precendence over the former.
180
+
181
+ === gRPC Interceptors
182
+
183
+ The gRPC API supports the notion of an interceptor on a channel. Interceptors are
184
+ useful to implement cross-cutting concerns that apply to many or all invocations.
185
+ These may include security, logging, metrics, etc. They can be specified directly
186
+ on the channel returned by a `GrpcClient`, effectively _wrapping_ that channel
187
+ with a list of interceptors to execute on every invocation.
188
+
189
+ [source,java]
190
+ ----
191
+ include::{sourcedir}/se/grpc/ClientSnippets.java[tag=snippet_10, indent=0]
192
+ ----
193
+
194
+ == Configuration
195
+
196
+ TLS can be configured externally, just like it is done when using the
197
+ WebClient to access an HTTP endpoint. For more information see
198
+ https://helidon.io/docs/v4/se/webclient#_configuring_the_webclient[Configuring the WebClient].
35
199
36
- If you require gRPC client, either stay with a previous version of Helidon, or allow us to finish fixing the issue above.
0 commit comments