gRPC NotImplementedException 尽管方法被调用

gRPC NotImplementedException though method is called

我尝试在 java 中使用 protobuf 和 gRPC,同时遵循提供的基本教程,尽管我总是倾向于创建自己的场景并从头开始构建所有内容。与复制粘贴教程代码和 运行 相比,我通过这种方式学得更好。

我创建了以下项目 (https://github.com/IngoHenkel/protobuf_test),其中包含一个服务 class 和两个服务,一个同步服务只是 return 一个服务器信息,一个异步服务模拟一个 long运行ning 任务 returning 流中的数据。

...
service DeepThoughtServices {
    rpc WhoAreYou (google.protobuf.Empty) returns  (WhoAmI) {}
    rpc RequestIntegerTokens(CalculateIntegerTokens) returns (stream IntegerToken) {}
}
...

第一个服务 (WhoAreYou) 工作得很好,但对于另一个服务,我总是在客户端上收到 NotImplementedException。 奇怪的是,该方法本身在服务器上被调用得很好(您可以从日志中看到),但是当我尝试将“onNext”方法调用到 return 数据时,我得到了异常:

java.lang.IllegalStateException: Stream was terminated by error, no further calls are allowed
    at com.google.common.base.Preconditions.checkState(Preconditions.java:502)
    at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onNext(ServerCalls.java:374)
    at de.squirrelsquad.tutorials.protobuf.protos.service.DeepThoughtServices.requestIntegerTokens(DeepThoughtServices.java:56)
    at de.squirrelsquad.tutorials.protobuf.protos.service.DeepThoughtServicesGrpc$MethodHandlers.invoke(DeepThoughtServicesGrpc.java:271)
    at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182)
    at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:340)
    at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListenerHalfClosed.runInContext(ServerImpl.java:866)
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:833)

。我首先认为这可能与我试图将“工作”分派到后台线程并从那里发送响应有关,但即使我现在只是直接在服务方法中发送响应,我仍然会收到错误消息。

客户端和服务器共享相同的代码库,您可以通过执行 mvn package 然后 运行 运行 它: java -jar target/grpc-test-0.0.1-SNAPSHOT-jar-with-dependencies.jar -s 8980 启动服务器和 ava -jar target/grpc-test-0.0.1-SNAPSHOT-jar-with-dependencies.jar -c localhost:8980 对于客户端,它将调用这两个方法然后 return.

有没有人知道这里出了什么问题?

查看 DeepThoughtServices.requestIntegerTokens() 的开头,我们看到:

public void requestIntegerTokens(CalculateIntegerTokens request, StreamObserver<IntegerToken> responseObserver) {
    // TODO Auto-generated method stub
    logger.info("Request integer tokens called");
    super.requestIntegerTokens(request, responseObserver);
    responseObserver.onNext(IntegerToken.newBuilder().setValue(1).build());

最后一行抛出 IllegalStateException

问题是super.requestIntegerTokens()DeepThoughtServicesImplBase 为每个方法都提供了默认实现,这些方法使 RPC 失败并带有 UNIMPLEMENTED。这允许在不破坏现有代码的情况下向 .proto 中的服务添加新方法。

要解决您的问题,只需删除对 super:

的调用
public void requestIntegerTokens(CalculateIntegerTokens request, StreamObserver<IntegerToken> responseObserver) {
    // TODO Auto-generated method stub
    logger.info("Request integer tokens called");
    // DON'T DELEGATE TO SUPER!
    //super.requestIntegerTokens(request, responseObserver);
    responseObserver.onNext(IntegerToken.newBuilder().setValue(1).build());