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.
有没有人知道这里出了什么问题?
- 尝试直接在“主”线程中调用方法(不分派)
- 玩过包和 class 名字
查看 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());
我尝试在 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.
有没有人知道这里出了什么问题?
- 尝试直接在“主”线程中调用方法(不分派)
- 玩过包和 class 名字
查看 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());