Table of Contents
- Introduction
- Features
- Getting
- Samples
- Usage
- Server
- Create and start a server
- Multi-Servers
- @GrpcService
- @GrpcServerInterceptor
- AbstractServerInterceptor and SimpleServerInterceptor
- MetadataServerInterceptor
- DefaultGrpcServerConfigurer and DefaultGrpcServerConfigureHelper
- GrpcServerFactory and DefaultGrpcServerFactory
- GrpcServersFactory and DefaultGrpcServersFactory
- Server Configuration Properties Table
- Client
- Create a Client
- Multi-Clients:
- Load Balance
- ClientInterceptor
- @ClientInterceptor
- AbstractClientInterceptor and SimpleClientInterceptor
- DefaultGrpcChannelConfigurer and DefaultGrpcChannelConfigureHelper
- GrpcChannelFactory, DefaultGrpcChannelFactory, GrpcStubFactory and DefaultGrpcStubFactory
- GrpcTargetResolver and DefaultGrpcTargetResolver
- Client Configuration Properties Table
- Web
- Server
This is a concise, clear, easy to extend and high-customizable gRPC spring-boot starter, with spring-boot style.
It needs Spring Boot 2+ and JDK1.8+.
-
Simply use
@GrpcService,@GrpcServerInterceptorand spring bean annotation such as@Componentto register gRPC service and server interceptors; -
Simply use
@GrpcClient,@GrpcClientInterceptorand spring bean annotation such as@Componentto register gRPC stub, channel and client interceptors; -
Support multi-servers;
-
Provide simple way to client load-balance;
-
Fine-grained control for servers/clients and service and interceptors.
Get grpc-spring-boot:
implementation("xyz.srclab.grpc.spring.boot:grpc-spring-boot-starter-server:0.0.1")
implementation("xyz.srclab.grpc.spring.boot:grpc-spring-boot-starter-client:0.0.1")
implementation("xyz.srclab.grpc.spring.boot:grpc-spring-boot-starter-web:0.0.1")
Use bom:
api platform("xyz.srclab.grpc.spring.boot:grpc-spring-boot-starter-bom:0.0.1")
Get grpc-spring-boot:
<dependencies>
<dependency>
<groupId>xyz.srclab.grpc.spring.boot</groupId>
<artifactId>grpc-spring-boot-starter-server</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>xyz.srclab.grpc.spring.boot</groupId>
<artifactId>grpc-spring-boot-starter-client</artifactId>
<version>0.0.1</version>
</dependency>
<dependency>
<groupId>xyz.srclab.grpc.spring.boot</groupId>
<artifactId>grpc-spring-boot-starter-web</artifactId>
<version>0.0.1</version>
</dependency>
</dependencies>
Use bom:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>xyz.srclab.grpc.spring.boot</groupId>
<artifactId>grpc-spring-boot-starter-bom</artifactId>
<version>0.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
https://github.com/srclab-projects/grpc-spring-boot
To create a gRPC server, first we add server properties in application.yml (or .yaml, .properties):
grpc:
server:
servers:
server1:
host: 127.0.0.1
port: 6565
Now we have a gRPC server called server1 with address:
127.0.0.1:6565. Then we add service on server1:
@Service
public class DefaultHelloService extends DefaultHelloServiceGrpc.DefaultHelloServiceImplBase {
@Override
public void hello(HelloRequest request, StreamObserver<HelloResponse> responseObserver) {
responseObserver.onNext(HelloResponse.newBuilder()
.setMessage("DefaultHelloService")
.setThreadName(Thread.currentThread().getName())
.build()
);
responseObserver.onCompleted();
}
}
Now server1 has a gRPC service DefaultHelloService. If we run the
application, server1 will be auto-start.
If we need two servers that one on 6565 and another on 6566, and
they share the host localhost:
grpc:
server:
defaults:
host: 127.0.0.1
servers:
server1:
port: 6565
server2:
port: 6566
defaults property has same properties with each server property.
server properties will auto-inherit defaults properties which is not
overridden.
By default, if a gRPC service class is annotated by @Service or other
spring-boot component annotation, it will work for all servers. Thus,
DefaultHelloService will work for both server1 and server2. If we
want DefaultHelloService only works for server1:
@GrpcService("server1")
public class DefaultHelloService{}
@GrpcService(serverPatterns = "server1")
public class DefaultHelloService{}
@GrpcService(serverPatterns = "*1")
public class DefaultHelloService{}
@GrpcService can specify the servers which gRPC service works for, by
bean name declared on value or serverPatterns, and it supports
ant-pattern. Now DefaultHelloService only works for server1.
Adding server interceptor is same with adding gRPC server:
@Component
public class DefaultServerInterceptor extends BaseServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
if (Objects.equals(call.getMethodDescriptor().getServiceName(), "HelloService2")) {
helloService2.addInterceptorTrace("DefaultServerInterceptor");
}
return super.interceptCall(call, headers, next);
}
}
DefaultServerInterceptor will work for all gRPC services
(DefaultHelloService), to limit it, use @GrpcServerInterceptor:
@GrpcServerInterceptor(value = "*hello*", order = -2)
public class DefaultServerInterceptor{}
@GrpcServerInterceptor(servicePatterns = "*hello*", order = -3)
public class DefaultServerInterceptor{}
Just like @GrpcService, @GrpcServerInterceptor can specify service
bean name pattern and support ant-pattern. The order property
specifies callback order, from low to high. Now
DefaultServerInterceptor only works for gRPC service whose bean name
matches *hello*.
ServerInterceptor is confusing (think about its nested calling,
callback execution order). For convenience this starter provides
AbstractServerInterceptor and SimpleServerInterceptor.
AbstractServerInterceptor is a skeletal implementation of
ServerInterceptor, provides serials of callback methods to override,
in simple order: intercept1 → intercept2 → onMessage2 → onMessage1
(detail see its javadoc).
SimpleServerInterceptor is an interface provides serials of callback
methods to override same with AbstractServerInterceptor.
Difference:
-
Each
AbstractServerInterceptoris aServerInterceptorinstance but allSimpleServerInterceptorin a gRPC service will be merged to oneServerInterceptor; -
Callback order is: intercept1 → intercept2 → onMessage1 → onMessage2 (detail see its javadoc).
MetadataServerInterceptor is a simple ServerInterceptor to do with
metadata (headers).
By default, this starter uses InProcessBuilder, NettyServerBuilder
and ShadedNettyServerBuilder to create new gRPC server. If you want to
custom them, create a new bean of DefaultGrpcServerConfigurer and use
bean DefaultGrpcServerConfigureHelper to help.
This starter uses GrpcServerFactory to create a new gRPC server, its
default implementation is DefaultGrpcServerFactory. If you want to
custom this process, create a new bean of GrpcServerFactory to
instead.
Note
|
DefaultGrpcServerConfigurer will invalid if you have a custom GrpcServerFactory bean, but DefaultGrpcServerConfigureHelper can be used still. |
This starter uses GrpcServersFactory to create all gRPC server, its
default implementation is DefaultGrpcServersFactory. If you want to
custom this process, create a new bean of GrpcServersFactory to
instead.
Note
|
DefaultGrpcServerFactory and DefaultGrpcServerConfigurer will invalid if you have a custom GrpcServersFactory bean, but DefaultGrpcServerConfigureHelper can be used still. |
| Key | Type | Default | Comment |
|---|---|---|---|
defaults |
|||
servers |
Map<String, ServerProperties> |
||
needGrpcAnnotation |
Boolean |
false |
Whether gRPC bean ( This means spring-boot annotation such as Default is false. |
Table 1. GrpcServersProperties
| Key | Type | Default | Comment |
|---|---|---|---|
inProcess |
Boolean |
false |
|
useShaded |
Boolean |
false |
|
host |
String |
localhost |
|
port |
Int |
6565 |
|
threadPoolBeanName |
String |
Thread pool bean name for gRPC executor. |
|
maxConcurrentCallsPerConnection |
Int |
||
initialFlowControlWindow |
Int |
||
flowControlWindow |
Int |
||
maxMessageSize |
Int |
||
maxHeaderListSize |
Int |
||
keepAliveTimeInNanos |
Long |
||
keepAliveTimeoutInNanos |
Long |
||
maxConnectionIdleInNanos |
Long |
||
maxConnectionAgeInNanos |
Long |
||
maxConnectionAgeGraceInNanos |
Long |
||
permitKeepAliveWithoutCalls |
Boolean |
||
permitKeepAliveTimeInNanos |
Long |
||
sslCertChainClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslTrustCertCollectionClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslCertChainFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslTrustCertCollectionFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyPassword |
String |
||
sslClientAuth |
String |
Auth enum with case-ignore: Default is |
Table 2. ServerProperties
To create a gRPC client, first we add client properties in application.yml (or .yaml, .properties):
grpc:
client:
clients:
client1:
target: 127.0.0.1:6565
Now we have a gRPC client called client1 with target:
127.0.0.1:6565. Then we add stub and channel on client1:
public class TestBean {
@GrpcClient
private DefaultHelloServiceGrpc.DefaultHelloServiceBlockingStub stub1;
@GrpcClient
private Channel channel1;
}
Now, stub1 and channel1 will be auto-wired with client1's
properties when application starts.
If we need two clients, for target 127.0.0.1:6565 and
127.0.0.1:6566:
grpc:
client:
clients:
client1:
target: 127.0.0.1:6565
client2:
target: 127.0.0.1:6566
Then:
public class TestBean {
@GrpcClient
private DefaultHelloServiceGrpc.DefaultHelloServiceBlockingStub defaultStub;
@GrpcClient("client1")
private HelloServiceXGrpc.HelloServiceXBlockingStub client1Stub;
@GrpcClient("client2")
private HelloService2Grpc.HelloService2BlockingStub client2Stub;
}
If no client name specified on @GrpcClient, it will auto-wired with
first client name (here is client1).
Note
|
Client configuration also inherit defaults properties like Multi-Servers. |
To set a load-balance target:
grpc:
client:
clients:
lb:
target: lb:127.0.0.1/127.0.0.1:6666,127.0.0.1/127.0.0.1:6667
Now the client lb is load-balance.
Note
|
load balance syntax is: lb:authority1/host1:port1,authority2/host2:port2… |
To declare a ClientInterceptor, just give a bean of
ClientInterceptor type:
@Component
public class DefaultClientInterceptor extends BaseClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
if (Objects.equals(method.getServiceName(), "HelloService2")) {
traceService.addInterceptorTrace("DefaultClientInterceptor");
}
return super.interceptCall(method, callOptions, next);
}
}
Now we have a DefaultClientInterceptor as ClientInterceptor for all
client.
To specify interceptor work in fine-grained, use
@GrpcServerInterceptor:
@GrpcClientInterceptor(value = "*2", order = 0)
public class DefaultClientInterceptor{}
@GrpcClientInterceptor(clientPatterns = "*2", order = -3)
public class DefaultClientInterceptor{}
value or clientPatterns specifies which client
DefaultClientInterceptor work for, support ant-pattern. For now, it
only works for client whose bean name matches \*2.
ClientInterceptor is confusing (think about its nested calling,
callback execution order). For convenience this starter provides
AbstractClientInterceptor and SimpleClientInterceptor.
AbstractClientInterceptor is a skeletal implementation of
ClientInterceptor, provides serials of callback methods to override,
in simple order: intercept1 → intercept2 → onClose2 → onClose1 (detail
see its javadoc).
SimpleClientInterceptor is an interface provides serials of callback
methods to override same with AbstractClientInterceptor.
Difference:
-
Each
AbstractClientInterceptoris aClientInterceptorinstance but allSimpleClientInterceptorin a gRPC channel will be merged to oneClientInterceptor; -
Callback order is: intercept1 → intercept2 → onClose1 → onClose2 (detail see its javadoc).
By default, this starter uses InProcessBuilder, NettyServerBuilder
and ShadedNettyServerBuilder, if you want to custom them, create a new
bean of DefaultGrpcChannelConfigurer and use bean
DefaultGrpcChannelConfigureHelper to help.
This starter uses GrpcChannelFactory to create a new gRPC stub, use
GrpcStubFactory to create a new gRPC channel. Default implementation
is DefaultGrpcChannelFactory and DefaultGrpcStubFactory. If you want
to custom this process, create a new bean of GrpcChannelFactory or
GrpcStubFactory.
Note
|
DefaultGrpcChannelConfigurer will invalid if you have a custom GrpcChannelFactory bean, but DefaultGrpcChannelConfigureHelper can be used still. |
This starter will register LbNameResolverProvider to resolve load
balance target (lb:authority/host1:port1,host2:port2…). By default,
LbNameResolverProvider use DefaultGrpcTargetResolver to resolve, to
custom this process, create bean of GrpcTargetResolver to instead.
| Key | Type | Default | Comment |
|---|---|---|---|
defaults |
|||
servers |
Map<String, ClientProperties> |
||
needGrpcAnnotation |
Boolean |
false |
Whether gRPC bean This means spring-boot annotation such as Default is false. |
Table 3. GrpcClientsProperties
| Key | Type | Default | Comment |
|---|---|---|---|
inProcess |
Boolean |
false |
|
useShaded |
Boolean |
false |
|
target |
String |
localhost:6565 |
Address or load balance ( |
threadPoolBeanName |
String |
Thread pool bean name for gRPC executor. |
|
initialFlowControlWindow |
Int |
||
flowControlWindow |
Int |
||
maxMessageSize |
Int |
||
maxHeaderListSize |
Int |
||
keepAliveTimeInNanos |
Long |
||
keepAliveTimeoutInNanos |
Long |
||
keepAliveWithoutCalls |
Boolean |
||
deadlineAfterInNanos |
Long |
||
loadBalancingPolicy |
String |
round_robin |
Load balance policy: Default is |
sslCertChainClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslTrustCertCollectionClassPath |
String |
Same classpath and file properties are alternative and classpath first |
|
sslCertChainFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslTrustCertCollectionFile |
String |
Same classpath and file properties are alternative and classpath first |
|
sslPrivateKeyPassword |
String |
||
sslClientAuth |
String |
Auth enum with case-ignore: Default is |
Table 4. ClientProperties
grpc-spring-boot-starter-web is used for making Controller support
protobuf Message type.
By default, it uses Jackson2ObjectMapperBuilderCustomizer.