我有一个 GRPC API,在重构之后,其中一些包被重命名。这包括package我们定义 API 的 proto 文件之一中的声明。像这样的东西:
package foo;
service BazApi {
rpc FooEventStream(stream Ack) returns (stream FooEvent);
}
Run Code Online (Sandbox Code Playgroud)
改为
package bar;
service BazApi {
rpc FooEventStream(stream Ack) returns (stream FooEvent);
}
Run Code Online (Sandbox Code Playgroud)
服务器端是grpc-java在顶部使用scala 和 monix 实现的。
这对于使用新 proto 文件的客户端来说一切正常,但对于构建在旧 proto 文件之上的旧客户端,这会导致问题:UNIMPLEMENTED: Method not found: foo.BazApi/FooEventStream.
通过 GRPC API 传递的消息的实际数据格式没有改变,只是包。
由于我们需要保持向后兼容性,我一直在寻找一种方法来让旧客户端正常工作,同时保持名称更改。
我希望ServerInterceptor使用能够检查传入呼叫的泛型来完成这项工作,看到它来自旧客户端(我们在标头中有客户端版本)并将其重定向/转发到重命名的服务。(因为只是包名发生了变化,这很容易弄清楚,例如foo.BazApi/FooEventStream-> bar.BazApi/FooEventStream)
但是,似乎没有一种优雅的方法可以做到这一点。我认为可以通过ClientCall为正确的端点启动一个新端点,然后ServerCall通过委托给ClientCall.
有一个更好的方法吗?
如果您可以轻松更改服务器,则可以让它同时支持这两个名称。您可以考虑使用两个不同的描述符注册服务两次的解决方案。
每个服务都有一个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"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1591 次 |
| 最近记录: |