|
| 1 | +[[client]] |
| 2 | += GRPC Client |
| 3 | + |
| 4 | +This section describes core concepts that Spring gRPC uses on the client side. |
| 5 | + |
| 6 | +== Create a `Channel` |
| 7 | + |
| 8 | +You can inject a `GrpcChannelFactory` into your application configuration and use it to create a gRPC channel. |
| 9 | +The most common usage of a channel is to create a client that binds to a service. |
| 10 | +The Protobuf-generated sources in your project will contain the stub classes, and they just need to be bound to a channel. |
| 11 | +The Protobuf files will be provided by the service you are connecting to. |
| 12 | +For example, consider the `SimpleGrpc` service generated by the Protobuf tooling in your build. |
| 13 | +To bind to this service on a local server: |
| 14 | + |
| 15 | +[source,java] |
| 16 | +---- |
| 17 | +@Bean |
| 18 | +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) { |
| 19 | + return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:9090").build()); |
| 20 | +} |
| 21 | +---- |
| 22 | + |
| 23 | +The `GrpcChannelFactory` creates a `ChannelBuilder` that you can customize before building the channel if necessary. |
| 24 | + |
| 25 | +=== Shaded Netty Client |
| 26 | + |
| 27 | +The default client implementation uses the Netty client. |
| 28 | +You can switch to a shaded Netty implementation provided by the gRPC team by adding the `grpc-netty-shaded` dependency and excluding the `grpc-netty` dependency. |
| 29 | + |
| 30 | +[source,xml] |
| 31 | +---- |
| 32 | +<dependency> |
| 33 | + <groupId>org.springframework.grpc</groupId> |
| 34 | + <artifactId>spring-grpc-spring-boot-starter</artifactId> |
| 35 | + <exclusions> |
| 36 | + <exclusion> |
| 37 | + <groupId>io.grpc</groupId> |
| 38 | + <artifactId>grpc-netty</artifactId> |
| 39 | + </exclusion> |
| 40 | + </exclusions> |
| 41 | +</dependency> |
| 42 | +<dependency> |
| 43 | + <groupId>io.grpc</groupId> |
| 44 | + <artifactId>grpc-netty-shaded</artifactId> |
| 45 | +</dependency> |
| 46 | +---- |
| 47 | + |
| 48 | +For Gradle users |
| 49 | + |
| 50 | +[source,gradle] |
| 51 | +---- |
| 52 | +dependencies { |
| 53 | + implementation "org.springframework.grpc:spring-grpc-spring-boot-starter" |
| 54 | + modules { |
| 55 | + module("io.grpc:grpc-netty") { |
| 56 | + replacedBy("io.grpc:grpc-netty-shaded", "Use Netty shaded instead of regular Netty") |
| 57 | + } |
| 58 | + } |
| 59 | +} |
| 60 | +---- |
| 61 | + |
| 62 | +== Channel Configuration |
| 63 | + |
| 64 | +The default `GrpcChannelFactory` implementation can also create a "named" channel, which you can then use to extract the configuration to connect to the server. |
| 65 | +For example: |
| 66 | + |
| 67 | +[source,java] |
| 68 | +---- |
| 69 | +@Bean |
| 70 | +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels) { |
| 71 | + return SimpleGrpc.newBlockingStub(channels.createChannel("local").build()); |
| 72 | +} |
| 73 | +---- |
| 74 | + |
| 75 | +then in `application.properties`: |
| 76 | + |
| 77 | +[source,properties] |
| 78 | +---- |
| 79 | +spring.grpc.client.channels.local.address=0.0.0.0:9090 |
| 80 | +---- |
| 81 | + |
| 82 | +There is a default named channel (named "default") that you can configure in the same way, and then it will be used by default if there is no channel with the name specified in the channel creation. |
| 83 | + |
| 84 | +Beans of type `GrpcChannelConfigurer` can be used to customize the `ChannelBuilder` before the channel is built. |
| 85 | +This can be useful for setting up security, for example. |
| 86 | + |
| 87 | +== The Local Server Port |
| 88 | + |
| 89 | +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. |
| 90 | +It can be convenient in that case to use an ephemeral port for the server (`spring.grpc.server.port=0`) and then use the port that is allocated to connect to it. |
| 91 | +You can discover the port that the server is running on by injecting the `@LocalGrpcPort` bean into your test. |
| 92 | +The `@Bean` has to be marked as `@Lazy` to ensure that the port is available when the bean is created (it is only known when the server starts which is part of the startup process). |
| 93 | + |
| 94 | +[source,java] |
| 95 | +---- |
| 96 | +@Bean |
| 97 | +@Lazy |
| 98 | +SimpleGrpc.SimpleBlockingStub stub(GrpcChannelFactory channels, @LocalGrpcPort int port) { |
| 99 | + return SimpleGrpc.newBlockingStub(channels.createChannel("0.0.0.0:" + port).build()); |
| 100 | +} |
| 101 | +---- |
0 commit comments