背景
用Java Springboot起一个grpc服务,参照官方示例,但是启动后用Postman或者其他客户端调用时,不论调用什么方法,都是报 12 UNIMPLEMENTED
。而且服务端日志里显示Stream was terminated by error, no further calls are allowed
。
报错信息如下:
2023-07-07 21:55:28.433 [grpc-default-executor-0] ERROR io.grpc.internal.SerializingExecutor- Exception while executing runnable io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed@30f27e20
java.lang.IllegalStateException: Stream was terminated by error, no further calls are allowed
at com.google.common.base.Preconditions.checkState(Preconditions.java:511)
at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onNext(ServerCalls.java:359)
at com.example.app.report.service.grpc.ReportServiceImpl.reportCompletion(ReportServiceImpl.java:16)
at com.example.app.report.proto.generated.ReportServiceGrpc$MethodHandlers.invoke(ReportServiceGrpc.java:312)
at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:331)
at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:797)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:123)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:750)
关键代码如下:
public class ReportServiceImpl extends ReportServiceGrpc.ReportServiceImplBase {
@Override
public void report(ReportEvent request, StreamObserver<ReportResponse> responseObserver) {
super.report(request, responseObserver);
responseObserver.onNext(ReportResponse.newBuilder().setCode(0).build());
responseObserver.onCompleted();
}
}
解决过程
在方法中打日志,这个方法确实被调用了。而且开启grpc服务端反射以后,也能读取到这个方法。
反复和官方示例对比,最后发现IDEA自动补全的Override代码里,会自动调用super类的方法。而这个方法,默认就会返回一个Unimplemented响应。
// 生成的reportService.java文件
...
public void reportCompletion(com.example.app.report.proto.generated.CompletionEvent request,
io.grpc.stub.StreamObserver<com.example.app.report.proto.generated.ReportResponse> responseObserver) {
io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getReportCompletionMethod(), responseObserver); // 默认返回未实现响应
}
...
解决方案
只需要把自动生成的调用super类的方法删掉即解决。
这个错误确实没有什么资料,而且比较低级,在此记录一下。
关键词
Java Springboot Grpc Unimplemented