Grpc.Core.RpcException 方法未通过 C# 客户端和 Java 服务器实现
Grpc.Core.RpcException method is unimplemented with C# client and Java Server
我找不到这个错误的根源。我使用 protobuf 实现了一个简单的服务:
syntax = "proto3";
package tourism;
service RemoteService {
rpc Login(LoginUserDTO) returns (Response) {}
}
message AgencyDTO{
int32 id=1;
string name=2;
string email=3;
string password=4;
}
message LoginUserDTO{
string password=1;
string email=2;
}
message SearchAttractionsDTO{
string name=1;
int32 start_hour=2;
int32 start_minute=3;
int32 stop_hour=4;
int32 stop_minute=5;
AgencyDTO loggedUser=6;
}
message AttractionDTO{
int32 id=1;
string name=2;
string agency=3;
int32 hour=4;
int32 minute=5;
int32 seats=6;
int32 price=7;
}
message ReservationDTO{
int32 id=1;
string first_name=2;
string last_name=3;
string phone=4;
int32 seats=5;
AttractionDTO attraction=6;
AgencyDTO agency=7;
}
message Response{
enum ResponseType{
OK=0;
NOT_LOGGED_ID=1;
SERVER_ERROR=2;
VALIDATOR_ERROR=3;
}
ResponseType type=1;
AgencyDTO user=2;
string message=3;
}
使用 java 客户端时一切正常,服务器接收请求并做出适当响应。当使用 C# 和相同的 .proto 文件在 client.Login() 生成源代码时,我得到以下错误:Grpc.Core.RpcException Status(StatusCode=Unimplemented, Detail="Method tourism.RemoteService/Login is unimplemented")。服务器收到请求但没有时间响应并抛出:
INFO: Request from ex@ex.com
May 22, 2017 12:28:58 AM io.grpc.internal.SerializingExecutor run
SEVERE: Exception while executing runnable io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener@4be43082
java.lang.IllegalStateException: call is closed
at com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at io.grpc.internal.ServerCallImpl.sendHeaders(ServerCallImpl.java:103)
at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onNext(ServerCalls.java:282)
at ServiceImp.login(ServiceImp.java:20)
at tourism.RemoteServiceGrpc$MethodHandlers.invoke(RemoteServiceGrpc.java:187)
at io.grpc.stub.ServerCalls.onHalfClose(ServerCalls.java:148)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:262)
at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener.runInContext(ServerImpl.java:572)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:52)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Java 服务器:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import tourism.RemoteServiceGrpc;
import tourism.Service;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by Andu on 21/05/2017.
*/
public class ServerGrpc {
Logger logger= Logger.getLogger(ServerGrpc.class.getName());
private final Server server;
private final int port;
public ServerGrpc(int p){
port=p;
server= ServerBuilder.forPort(port).addService(new ServiceImp()).build();
}
public void start() throws IOException {
server.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may has been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
ServerGrpc.this.stop();
System.err.println("*** server shut down");
}
});
}
public void stop() {
if (server != null) {
server.shutdown();
}
}
void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
private class ServiceImp extends RemoteServiceGrpc.RemoteServiceImplBase {
Logger log=Logger.getLogger(ServiceImp.class.getName());
@Override
public void login(Service.LoginUserDTO request, StreamObserver<Service.Response> responseStreamObserver){
super.login(request,responseStreamObserver);
log.log(Level.INFO,"Request from "+request.getEmail());
Service.Response response= Service.Response.newBuilder().setMessage("Hello "+request.getEmail()+", I know your password: "+request.getPassword()).build();
responseStreamObserver.onNext(response);
responseStreamObserver.onCompleted();
}
}
}
C# 客户端:
namespace testGrpc2
{
class MainClass
{
public static void Main(string[] args)
{
var channel = new Channel("127.0.0.1:61666",ChannelCredentials.Insecure);
var client = new RemoteService.RemoteServiceClient(channel);
Response response=client.Login(new LoginUserDTO{Email="ex@ex.com",Password="notmypassword"});
Console.WriteLine(response);
Console.ReadKey();
}
}
}
我设法找到了问题的根源。对于遇到此问题的其他人:
Make sure your .proto file is identical for both client and server and it has the same package. When the client calls a method on the remote server, it uses the full name of the remote class and the package.
然而,这并不是该方法对客户端显示为未实现的原因。是这样的:
super.login(request,responseStreamObserver);
调用超级方法登录将异步未实现错误代码发送回客户端。这是生成的 class:
中的 login() 方法
public void login(LoginUserDTO request,StreamObserver<Response> responseObserver) {
asyncUnimplementedUnaryCall(METHOD_LOGIN, responseObserver);
}
So make sure in the implementation of your service methods you don't call the super method as it will appear to the client as UNIMPLEMENTED. If you generate @Override methods using IntelliJ IDEA it will add the super method call. Make sure to delete it.
感谢 Alexandru - 这帮助我解决了 Akka gRPC 客户端和 Python grPC 服务器的问题。在我的例子中,我在 .proto 文件中有相同的包和序言,但在 Python gRPC 服务器中删除了消息 类 和这个特定用例不需要的 gRPC 函数。当我使 .proto 文件相同时,一切正常,我不再收到 UNIMPLEMENTED 错误。对于引用的 C#/Java 示例以外的语言,这是必需的。再次感谢。
对我来说,是我忘记在启动时添加 gRpc 服务端点 class。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
//Add your endpoint here like this
endpoints.MapGrpcService<YourProtoService>();
});
对我来说,使用 C# 客户端,问题是我没有覆盖生成的服务方法。
我的服务器和客户端都是java,在IntelliJ中关闭再打开项目后问题解决了!!
我找不到这个错误的根源。我使用 protobuf 实现了一个简单的服务:
syntax = "proto3";
package tourism;
service RemoteService {
rpc Login(LoginUserDTO) returns (Response) {}
}
message AgencyDTO{
int32 id=1;
string name=2;
string email=3;
string password=4;
}
message LoginUserDTO{
string password=1;
string email=2;
}
message SearchAttractionsDTO{
string name=1;
int32 start_hour=2;
int32 start_minute=3;
int32 stop_hour=4;
int32 stop_minute=5;
AgencyDTO loggedUser=6;
}
message AttractionDTO{
int32 id=1;
string name=2;
string agency=3;
int32 hour=4;
int32 minute=5;
int32 seats=6;
int32 price=7;
}
message ReservationDTO{
int32 id=1;
string first_name=2;
string last_name=3;
string phone=4;
int32 seats=5;
AttractionDTO attraction=6;
AgencyDTO agency=7;
}
message Response{
enum ResponseType{
OK=0;
NOT_LOGGED_ID=1;
SERVER_ERROR=2;
VALIDATOR_ERROR=3;
}
ResponseType type=1;
AgencyDTO user=2;
string message=3;
}
使用 java 客户端时一切正常,服务器接收请求并做出适当响应。当使用 C# 和相同的 .proto 文件在 client.Login() 生成源代码时,我得到以下错误:Grpc.Core.RpcException Status(StatusCode=Unimplemented, Detail="Method tourism.RemoteService/Login is unimplemented")。服务器收到请求但没有时间响应并抛出:
INFO: Request from ex@ex.com
May 22, 2017 12:28:58 AM io.grpc.internal.SerializingExecutor run
SEVERE: Exception while executing runnable io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener@4be43082
java.lang.IllegalStateException: call is closed
at com.google.common.base.Preconditions.checkState(Preconditions.java:174)
at io.grpc.internal.ServerCallImpl.sendHeaders(ServerCallImpl.java:103)
at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.onNext(ServerCalls.java:282)
at ServiceImp.login(ServiceImp.java:20)
at tourism.RemoteServiceGrpc$MethodHandlers.invoke(RemoteServiceGrpc.java:187)
at io.grpc.stub.ServerCalls.onHalfClose(ServerCalls.java:148)
at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:262)
at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener.runInContext(ServerImpl.java:572)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:52)
at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:117)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Java 服务器:
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;
import tourism.RemoteServiceGrpc;
import tourism.Service;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Created by Andu on 21/05/2017.
*/
public class ServerGrpc {
Logger logger= Logger.getLogger(ServerGrpc.class.getName());
private final Server server;
private final int port;
public ServerGrpc(int p){
port=p;
server= ServerBuilder.forPort(port).addService(new ServiceImp()).build();
}
public void start() throws IOException {
server.start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may has been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
ServerGrpc.this.stop();
System.err.println("*** server shut down");
}
});
}
public void stop() {
if (server != null) {
server.shutdown();
}
}
void blockUntilShutdown() throws InterruptedException {
if (server != null) {
server.awaitTermination();
}
}
private class ServiceImp extends RemoteServiceGrpc.RemoteServiceImplBase {
Logger log=Logger.getLogger(ServiceImp.class.getName());
@Override
public void login(Service.LoginUserDTO request, StreamObserver<Service.Response> responseStreamObserver){
super.login(request,responseStreamObserver);
log.log(Level.INFO,"Request from "+request.getEmail());
Service.Response response= Service.Response.newBuilder().setMessage("Hello "+request.getEmail()+", I know your password: "+request.getPassword()).build();
responseStreamObserver.onNext(response);
responseStreamObserver.onCompleted();
}
}
}
C# 客户端:
namespace testGrpc2
{
class MainClass
{
public static void Main(string[] args)
{
var channel = new Channel("127.0.0.1:61666",ChannelCredentials.Insecure);
var client = new RemoteService.RemoteServiceClient(channel);
Response response=client.Login(new LoginUserDTO{Email="ex@ex.com",Password="notmypassword"});
Console.WriteLine(response);
Console.ReadKey();
}
}
}
我设法找到了问题的根源。对于遇到此问题的其他人:
Make sure your .proto file is identical for both client and server and it has the same package. When the client calls a method on the remote server, it uses the full name of the remote class and the package.
然而,这并不是该方法对客户端显示为未实现的原因。是这样的:
super.login(request,responseStreamObserver);
调用超级方法登录将异步未实现错误代码发送回客户端。这是生成的 class:
中的 login() 方法public void login(LoginUserDTO request,StreamObserver<Response> responseObserver) {
asyncUnimplementedUnaryCall(METHOD_LOGIN, responseObserver);
}
So make sure in the implementation of your service methods you don't call the super method as it will appear to the client as UNIMPLEMENTED. If you generate @Override methods using IntelliJ IDEA it will add the super method call. Make sure to delete it.
感谢 Alexandru - 这帮助我解决了 Akka gRPC 客户端和 Python grPC 服务器的问题。在我的例子中,我在 .proto 文件中有相同的包和序言,但在 Python gRPC 服务器中删除了消息 类 和这个特定用例不需要的 gRPC 函数。当我使 .proto 文件相同时,一切正常,我不再收到 UNIMPLEMENTED 错误。对于引用的 C#/Java 示例以外的语言,这是必需的。再次感谢。
对我来说,是我忘记在启动时添加 gRpc 服务端点 class。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
//Add your endpoint here like this
endpoints.MapGrpcService<YourProtoService>();
});
对我来说,使用 C# 客户端,问题是我没有覆盖生成的服务方法。
我的服务器和客户端都是java,在IntelliJ中关闭再打开项目后问题解决了!!