Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gRPC client not working when called from within gRPC service

Quick disclaimer, I am very new to gRPC and RPC in general, so please have patience

I have two gRPC servers running on the same java application, Service A and Service B. Service A creates multiple clients of Service B which then synchronously makes calls to the various instances of Service B

The server

Service A has a rpc call defined by the .proto file as

rpc notifyPeers(NotifyPeersRequest) returns (NotifyPeersResponse);

the server side implementation,

@Override
public void notifyPeers(NotifyPeersRequest request, StreamObserver<NotifyPeersResponse> responseObserver) {
    logger.debug("gRPC 'notifyPeers' request received");
    String host = request.getHost();
    
   
    for (PeerClient c : clients.values()) {   
        c.addPeer(host);    // <----  this call
    }

    NotifyPeersResponse response = NotifyPeersResponse.newBuilder()
            .setResult(result)
            .build();

    responseObserver.onNext(response);
    responseObserver.onCompleted();
}

The list of peers, clients are built up in previous rpc calls.

ManagedChannel channel = ManagedChannelBuilder.forTarget(peer).usePlaintext().build();
ClientB client = new ClientB(channel);
clients.put(peer, client);

The client

rpc addPeer(AddPeerRequest) returns (AddPeerResponse);rpc addPeer(AddPeerRequest) returns (AddPeerResponse);

the server side implementation,

@Override
public void addPeer(AddPeerRequest addPeerRequest, StreamObserver<AddPeerResponse> responseObserver)  {
    logger.info("gRPC 'addPeer' request received");
    boolean result = peer.addPeer(host);
    AddPeerResponse response = AddPeerResponse.newBuilder()
                .setResponse(result)
                .build();
    responseObserver.onNext(response);
    responseObserver.onCompleted();

the client side implementation,

public boolean addPeer(String host) {
    AddPeerRequest request = AddPeerRequest.newBuilder().setHost(host).build();
    logger.info("Sending 'addPeer' request");
    AddPeerResponse response = blockingStub.addPeer(request);
    return response.getResponse();
}

When I run this application, and an RPC is made to Service A and the client connection is created that calls addPeer, an ambiguous exception is thrown, io.grpc.StatusRuntimeException: UNKNOWN which then causes the JVM to shut down. I have no idea how to fix this, or whether it is even possible to create an gRPC client connection within a gRPC server

for all of my gRPC server implementations I'm using blocking stubs.

<grpc.version>1.16.1</grpc.version> <java.version>1.8</java.version>

I've pretty much hit a brick wall, so any information will be appreciated

like image 759
Iggydv Avatar asked Jul 30 '20 18:07

Iggydv


People also ask

Are gRPC calls blocking?

gRPC supports non-blocking client calls. What this means is that when the client makes a call to the service, it does not need to wait for the server response. To handle the server response, the client can simply pass in the observer which dictates what to do when the response is received.

Can gRPC server handle multiple clients?

Multiple gRPC clients can be created from a channel, including different types of clients. A channel and clients created from the channel can safely be used by multiple threads. Clients created from the channel can make multiple simultaneous calls.

How does gRPC work internally?

The gRPC infrastructure decodes incoming requests, executes service methods, and encodes service responses. On the client side, the client has a local object known as stub (for some languages, the preferred term is client) that implements the same methods as the service.

Can a gRPC server also be a client?

Yes, you can definitely do that.

How does the gRPC client work?

The gRPC client will handle message serialization and addressing the gRPC call to the correct service. gRPC has different types of methods. How the client is used to make a gRPC call depends on the type of method called. The gRPC method types are:

Why does my gRPC client throw an error when calling a service?

A gRPC client throws an error when it calls a service and the connection-level security of the channel and service don't match. To configure a gRPC channel to use TLS, ensure the server address starts with https. For example, GrpcChannel.ForAddress ("https://localhost:5001") uses HTTPS protocol.

How do I call unsecured gRPC services with the client?

To call unsecured gRPC services, ensure the server address starts with http. For example, GrpcChannel.ForAddress ("http://localhost:5000") uses HTTP protocol. In .NET Core 3.1, additional configuration is required to call insecure gRPC services with the .NET client.

How do I make a gRPC call?

A gRPC call is initiated by calling a method on the client. The gRPC client will handle message serialization and addressing the gRPC call to the correct service. gRPC has different types of methods. How the client is used to make a gRPC call depends on the type of method called.


1 Answers

The UNKNOWN message is an exception on the server side that was not passed to the client. You probably need to increase the log level on the server to try to find the root cause.

In this post here , creating the channel like below, enable it to see a more meaningful error message:

ManagedChannel channel = NettyChannelBuilder.forAddress( host, port )
                .protocolNegotiator(ProtocolNegotiators.serverPlaintext() )
like image 193
edubriguenti Avatar answered Oct 27 '22 04:10

edubriguenti