gpt4 book ai didi

grpc - 一般转发 GRPC 调用

转载 作者:行者123 更新时间:2023-12-02 09:05:58 34 4
gpt4 key购买 nike

我有一个 GRPC API,经过重构,一些包被重命名。这包括我们定义 API 的原型(prototype)文件之一中的 package 声明。像这样的:

package foo;

service BazApi {
rpc FooEventStream(stream Ack) returns (stream FooEvent);
}

改成

package bar;

service BazApi {
rpc FooEventStream(stream Ack) returns (stream FooEvent);
}

服务器端使用 grpc-java 实现,顶部带有 scala 和 monix。

这对于使用新 proto 文件的客户端来说一切正常,但对于在旧 proto 文件之上构建的旧客户端,这会导致问题:UNIMPLEMENTED: Method not found: foo.BazApi/FooEventStream

通过 GRPC API 传递的消息的实际数据格式没有改变,只有包。

由于我们需要保持向后兼容性,我一直在寻找一种方法,让旧客户端在保持名称更改的同时正常工作。

我希望使用通用 ServerInterceptor 来完成这项工作,它能够检查传入调用,查看它来自旧客户端(我们在 header 中有客户端版本)并重定向/将其转发到重命名的服务。 (因为只是包名改变了,这很容易弄清楚,例如 foo.BazApi/FooEventStream -> bar.BazApi/FooEventStream)

但是,似乎没有一种优雅的方法可以做到这一点。我认为可以通过将新的 ClientCall 启动到正确的端点,然后通过委托(delegate)给 ClientCall 在拦截器中处理 ServerCall 来实现,但是这将需要一堆管道代码来正确处理 unary/clientStreaming/serverStreaming/bidiStreaming 调用。

有没有更好的方法来做到这一点?

最佳答案

如果您可以轻松更改服务器,则可以让它同时支持这两个名称。您可以考虑使用两个不同的描述符注册服务两次的解决方案。

每个服务都有一个 bindService()返回 ServerServiceDefinition 的方法。您可以通过普通的 serverBuilder.addService() 将定义传递给服务器。

这样你就可以得到正常的ServerServiceDefinition,然后重写成新的名字,然后注册新的名字。

BazApiImpl service = new BazApiImpl();
serverBuilder.addService(service); // register "bar"

ServerServiceDefinition barDef = service.bindService();
ServerServiceDefinition fooDefBuilder = ServerServiceDefinition.builder("foo.BazApi");
for (ServerMethodDefinition<?,?> barMethodDef : barDef.getMethods()) {
MethodDescriptor desc = barMethodDef.getMethodDescriptor();
String newName = desc.getFullMethodName().replace("foo.BazApi/", "bar.BazApi/");
desc = desc.toBuilder().setFullMethodName(newName).build();
foDefBuilder.addMethod(desc, barMethodDef.getServerCallHandler());
}
serverBuilder.addService(fooDefBuilder.build()); // register "foo"

关于grpc - 一般转发 GRPC 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58555788/

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