- 简介
- 特性
- 获取
- 样例
- 使用
- Server
- 创建一个服务
- 多Server服务
- @GrpcService
- @GrpcServerInterceptor
- AbstractServerInterceptor and SimpleServerInterceptor
- MetadataServerInterceptor
- DefaultGrpcServerConfigurer and DefaultGrpcServerConfigureHelper
- GrpcServerFactory and DefaultGrpcServerFactory
- GrpcServersFactory and DefaultGrpcServersFactory
- Server配置属性表
- Client
- 创建一个客户端
- 多客户端:
- 负载均衡
- ClientInterceptor
- @ClientInterceptor
- AbstractClientInterceptor and SimpleClientInterceptor
- DefaultGrpcChannelConfigurer and DefaultGrpcChannelConfigureHelper
- GrpcChannelFactory, DefaultGrpcChannelFactory, GrpcStubFactory and DefaultGrpcStubFactory
- GrpcTargetResolver and DefaultGrpcTargetResolver
- Client配置属性表
- Web
- Server
-
简单使用
@GrpcService,@GrpcServerInterceptor和spring注解如@Component来注册gRPC service和server interceptors; -
简单使用
@GrpcClient,@GrpcClientInterceptor和spring注解如@Component来注册gRPC stub, channel以及client interceptors; -
支持多server服务;
-
提供简单的方式进行客户端负载均衡;
-
细粒度的servers/clients以及它们的interceptors的控制.
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")api platform("xyz.srclab.grpc.spring.boot:grpc-spring-boot-starter-bom:0.0.1")<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><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>我们首先在application.yml (或者 .yaml, .properties)添加server的属性:
grpc:
server:
servers:
server1:
host: 127.0.0.1
port: 6565现在我们有了一个叫 server1 的服务, 在地址: 127.0.0.1:6565 上.
接下来我们在 server1 上添加service:
@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();
}
}现在 server1 有了一个 gRPC service DefaultHelloService.
如果我们运行项目, server1 将会自动启动.
如果我们需要在端口 6565 和 6566 上都开启服务, 并且他们共享主机 localhost:
grpc:
server:
defaults:
host: 127.0.0.1
servers:
server1:
port: 6565
server2:
port: 6566defaults 属性的子属性和 server 属性的子属性相同. server 属性将会自动注入 defaults 属性, 除了被覆盖配置的属性.
默认情况下, 如果一个 gRPC service 类被 @Service 或者其他 spring-boot 注解所注释, 它将为所有的服务工作.
因此, DefaultHelloService 将同时为 server1 和 server2 工作.
如果我们希望 DefaultHelloService 只为 server1 工作:
@GrpcService("server1")
public class DefaultHelloService{}
@GrpcService(serverPatterns = "server1")
public class DefaultHelloService{}
@GrpcService(serverPatterns = "*1")
public class DefaultHelloService{}@GrpcService 可以通过 value or serverPatterns 属性指定它愿意工作的服务名, 并且它支持 ant-pattern.
现在 DefaultHelloService 只为 server1 工作了.
添加拦截器和添加服务一样:
@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 将会为所有的 gRPC services (DefaultHelloService) 工作, 想要限制它, 使用 @GrpcServerInterceptor:
@GrpcServerInterceptor(value = "*hello*", order = -2)
public class DefaultServerInterceptor{}
@GrpcServerInterceptor(servicePatterns = "*hello*", order = -3)
public class DefaultServerInterceptor{}就像 @GrpcService, @GrpcServerInterceptor 可以指定 service bean 的名字, 并且支持 ant-pattern.
order 属性指定调用殊勋, 从低到高.
现在, DefaultServerInterceptor 只为匹配 *hello* 的服务提供拦截了.
ServerInterceptor 足以令人困惑 (想想看它的嵌套调用和回调顺序).
为了方便开发, 这个starter 提供 AbstractServerInterceptor 和 SimpleServerInterceptor.
AbstractServerInterceptor 是 ServerInterceptor 的快捷实现, 提供一系列的回调方法以供重写, 并且有一个简单的调用顺序: intercept1 → intercept2 → onMessage2 → onMessage1 (具体请参阅 javadoc).
SimpleServerInterceptor 是一个接口, 提供和 AbstractServerInterceptor 一样的回调方法一共重写.
区别:
-
每个
AbstractServerInterceptor都是一个ServerInterceptor实例, 但是所有的SimpleServerInterceptor对于每个 gRPC service 都将被合并成一个ServerInterceptor; -
回调顺序是: intercept1 → intercept2 → onMessage1 → onMessage2 (具体请参阅 javadoc).
MetadataServerInterceptor 是一个简单的 ServerInterceptor 用来处理 metadata (headers).
默认情况下, 这个starter使用 InProcessBuilder, NettyServerBuilder 和 ShadedNettyServerBuilder 来创建 gRPC server.
如果你想要定制这个过程, 创建一个 DefaultGrpcServerConfigurer bean 并且使用 bean DefaultGrpcServerConfigureHelper 来辅助设置.
这个starter使用 GrpcServerFactory 来创建 gRPC server, 它默认的实现是 DefaultGrpcServerFactory.
如果你想要定制这个过程, 创建一个 GrpcServerFactory bean 来替代.
|
Note
|
DefaultGrpcServerConfigurer 将会失效如果你创建了定制的 GrpcServerFactory bean, 但是 DefaultGrpcServerConfigureHelper 仍然可以使用.
|
这个starter使用 GrpcServersFactory 来创建所有的 gRPC server, 它默认的实现是 DefaultGrpcServersFactory.
如果你想要定制这个过程, 创建一个 GrpcServersFactory bean 来替代.
|
Note
|
DefaultGrpcServerFactory 和 DefaultGrpcServerConfigurer 将会失效如果你创建了定制的 GrpcServersFactory bean, 但是`DefaultGrpcServerConfigureHelper` 仍然可以使用.
|
| 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. |
| 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 |
我们首先在application.yml (或者 .yaml, .properties)添加client的属性:
grpc:
client:
clients:
client1:
target: 127.0.0.1:6565现在我们有了一个client叫 client1, target: 127.0.0.1:6565.
接着我们使用 client1 添加stub和channel:
public class TestBean {
@GrpcClient
private DefaultHelloServiceGrpc.DefaultHelloServiceBlockingStub stub1;
@GrpcClient
private Channel channel1;
}现在, stub1 和 channel1 在项目启动时将会使用 client1 的属性自动注入.
如果我们需要两个客户端, 用target 127.0.0.1:6565 和 127.0.0.1:6566:
grpc:
client:
clients:
client1:
target: 127.0.0.1:6565
client2:
target: 127.0.0.1:6566然后:
public class TestBean {
@GrpcClient
private DefaultHelloServiceGrpc.DefaultHelloServiceBlockingStub defaultStub;
@GrpcClient("client1")
private HelloServiceXGrpc.HelloServiceXBlockingStub client1Stub;
@GrpcClient("client2")
private HelloService2Grpc.HelloService2BlockingStub client2Stub;
}如果client的名字在 @GrpcClient 上没有被指定, 它将使用配置的第一个客户端 (这里是 client1).
|
Note
|
客户端配置也会继承 defaults 属性就像 多Server服务.
|
设置 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现在, client lb 被配置成负载均衡了.
|
Note
|
负载均衡的语法: lb:authority1/host1:port1,authority2/host2:port2…
|
申明一个 ClientInterceptor 只需要给一个 ClientInterceptor 类型的bean:
@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);
}
}现在我们有了一个 DefaultClientInterceptor 作为 ClientInterceptor, 它将为所有的client服务.
要细粒度的设置拦截器, use @GrpcServerInterceptor:
@GrpcClientInterceptor(value = "*2", order = 0)
public class DefaultClientInterceptor{}
@GrpcClientInterceptor(clientPatterns = "*2", order = -3)
public class DefaultClientInterceptor{}value 或者 clientPatterns 指定client DefaultClientInterceptor 为谁工作, 支持 ant-pattern.
现在, 它只为名字匹配 \*2 的client工作.
ClientInterceptor 足以令人困惑 (想想看它的嵌套调用和回调顺序).
为了方便开发, 这个starter 提供 AbstractClientInterceptor 和 SimpleClientInterceptor.
AbstractClientInterceptor 是 ClientInterceptor 的快捷实现, 提供一系列的回调方法以供重写, 并且有一个简单的调用顺序: intercept1 → intercept2 → onClose2 → onClose1 (具体请参阅 javadoc).
SimpleClientInterceptor 是一个接口, 提供和 AbstractClientInterceptor 一样的回调方法一共重写.
区别:
-
每个
AbstractClientInterceptor都是一个ClientInterceptor实例, 但是所有的SimpleClientInterceptor对于每个 gRPC service 都将被合并成一个ClientInterceptor; -
回调顺序是: intercept1 → intercept2 → onClose1 → onClose2 (具体请参阅 javadoc).
默认情况下, 这个starter使用 InProcessBuilder, NettyServerBuilder 和 ShadedNettyServerBuilder 来创建 gRPC client.
如果你想要定制这个过程, 创建一个 DefaultGrpcChannelConfigurer bean 并且使用 bean DefaultGrpcChannelConfigureHelper 来辅助设置.
这个starter使用 GrpcChannelFactory 来创建 gRPC stub, 使用 GrpcStubFactory 来创建 gRPC channel.
默认实现 DefaultGrpcChannelFactory 和 DefaultGrpcStubFactory.
如果你想要定制这个过程, 创建一个 GrpcChannelFactory bean 或者 GrpcStubFactory bean.
|
Note
|
DefaultGrpcChannelConfigurer 将会失效如果你创建了定制的 GrpcChannelFactory bean, 但是 DefaultGrpcChannelConfigureHelper 仍然可以使用.
|
这个starter会注册 LbNameResolverProvider 来解析负载均衡的 target (lb:authority/host1:port1,host2:port2…).
默认情况下, LbNameResolverProvider 使用 DefaultGrpcTargetResolver 来解析, 想要定制这个过程, 创建一个 GrpcTargetResolver bean 来替代.
| 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. |
| 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 |