gpt4 book ai didi

java - 如何直接从protobuf创建GRPC客户端而不将其编译成java代码

转载 作者:行者123 更新时间:2023-12-01 17:30:21 26 4
gpt4 key购买 nike

使用 gRPC 时,我们需要通过 Protocol Buffer 编译器 (protoc) 或使用 Gradle 或 Maven protoc 构建插件从 .proto 服务定义生成 gRPC 客户端和服务器接口(interface)。

Flow now: protobuf file -> java code -> gRPC client.

那么,有什么办法可以跳过这一步吗?

如何创建一个通用的 gRPC 客户端,可以直接从 protobuf 文件调用服务器,而无需编译成 java 代码?或者,有没有办法在运行时生成代码?

Flow expect: protobuf file -> gRPC client.

我想构建一个通用的 gRPC 客户端系统,输入是 protobuf 文件以及方法、包、消息请求的描述......而不必为每个 protobuf 再次编译。

非常感谢。

最佳答案

Protobuf 系统确实需要 protoc 才能运行。但是,可以跳过生成的代码。您可以传递 --descriptor_set_out=FILE 来解析 ,而不是将 --java_out--grpc_java_out 等传递给 protoc .proto 文件转换为描述符 文件。描述 rune 件是 proto-encoded FileDescriptorSet 。这与反射服务使用的基本格式相同。

一旦有了描述符,您就可以load it a FileDescriptor at a timecreate a DynamicMessage .

然后对于 gRPC 部分,您需要创建一个 gRPC MethodDescriptor。

static MethodDescriptor from(
Descriptors.MethodDescriptor methodDesc
) {
return MethodDescriptor.<DynamicMessage, DynamicMessage>newBuilder()
// UNKNOWN is fine, but the "correct" value can be computed from
// methodDesc.toProto().getClientStreaming()/getServerStreaming()
.setType(getMethodTypeFromDesc(methodDesc))
.setFullMethodName(MethodDescriptor.generateFullMethodName(
serviceDesc.getFullName(), methodDesc.getName()))
.setRequestMarshaller(ProtoUtils.marshaller(
DynamicMessage.getDefaultInstance(methodDesc.getInputType())))
.setResponseMarshaller(ProtoUtils.marshaller(
DynamicMessage.getDefaultInstance(methodDesc.getOutputType())))
.build();

static MethodDescriptor.MethodType getMethodTypeFromDesc(
Descriptors.MethodDescriptor methodDesc
) {
if (!methodDesc.isServerStreaming()
&& !methodDesc.isClientStreaming()) {
return MethodDescriptor.MethodType.UNARY;
} else if (methodDesc.isServerStreaming()
&& !methodDesc.isClientStreaming()) {
return MethodDescriptor.MethodType.SERVER_STREAMING;
} else if (!methodDesc.isServerStreaming()) {
return MethodDescriptor.MethodType.CLIENT_STREAMING);
} else {
return MethodDescriptor.MethodType.BIDI_STREAMING);
}
}

此时您已拥有所需的一切,可以调用 Channel.newCall(method, CallOptions.DEFAULT)在 gRPC 中。您也可以免费使用ClientCalls使用与 stub API 更相似的东西。

所以动态调用绝对是可能的,并且用于诸如grpcurl之类的事情。但这也并不容易,因此通常只在必要时才进行。

关于java - 如何直接从protobuf创建GRPC客户端而不将其编译成java代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61133529/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com