【发布时间】:2020-05-31 12:47:03
【问题描述】:
使用 GRPC 流式传输大量数据的最佳做法是什么? 我正在向将流回数据的 GRPC 服务器发送请求。发回的数据可以是大约 100 条 protobuf 消息,也可以是一对 100.000 条 protobuf 消息。
service CrossEngineSelector {
rpc QueryDB (QueryRequest) returns (stream QueryResponse) {}
}
服务器是发送 protobuf 消息的简单实现。
@Override
public void queryBD(QueryRequest request, StreamObserver<QueryResponse> responseObserver) {
Iterables.partition( dataLoader.getData(), 1000).forEach(batch -> {
responseObserver.onNext(QueryResponse.newBuilder().addAllRows(batch).build());
});
responseObserver.onCompleted();
}
客户端使用blockingStub调用该方法(protobuf生成代码):
public Iterator<QueryResponse> queryDB(QueryRequest request) {
return ClientCalls.blockingServerStreamingCall(this.getChannel(),
CrossEngineSelectorGrpc.getQueryEnginesMethod(),
this.getCallOptions(), request);
}
一旦客户端调用此方法,我只需遍历 QueryResponse。
所有这些都适用于只发回少量消息的流。一旦我尝试流式传输 100.000 条消息,max-inbound-message-size 会不断增加,最终会出现错误:RESOURCE_EXHAUSTED: Compressed gRPC message exceeds maximum size 4194304: 4196022 bytes read
我目前的解决方法是将 max-inbound-message-size 设置得非常高 +1Gb。这是一个硬编码的值,所以它不会缩放。客户端不知道服务器将返回多少条消息。我可能会遇到一些用例,即使 1Gb max-inbound-message-size 也不够用。
我希望我犯了一个实施错误。我希望有一种方法可以重置来自服务器的每个流 (onNext()) 的消息大小,或者它不断增加消息大小是否正常?
我假设单个 responseObserver.onNext(QueryResponse.newBuilder().addAllRows(batch).build()); 发送了几个 Mb,并且只要它运行,这将被视为消息大小而不是整个流。
我将 Micronaut 用于服务器和客户端。
【问题讨论】:
标签: java grpc micronaut grpc-java