Is it availble to do RPC requests from server to client with gRPC?

Viewed 5216

Foreword:

I didn't use gRPC before. I am only taking a first look on this technology and trying to understand if I can use it in my project or not. I am using C# with net core 2.1, if it matters for something.

Question:

I have one server and multiple clients and I need to do a RPC request from a server to a client. Is it availbale with gRPC? And if so, how can I do that?

3 Answers

Server initiated requests are not a first class feature of gRPC, however, this sort of PRC topography is always possible with streaming semantics.

For example, the flow would be:
1) all clients establish long lived streaming RPCs with the server
2) the server can now send messages to each client on those streams as if each message was an individual RPC

Answer from https://groups.google.com/forum/#!topic/grpc-io/wAF9T0nQcH0

Author of answer : Josh Humphries (Josh, if you will read this topic, pls post your answer here and i will accept it and will remove my copy)

You can use a bi-directional stream, where each message that the server sends on a stream will have a single message from the client in reply. The actual request and response types can both have a oneof: the response message has an option in the oneof for each actual RPC operation (and its request type); the request message (sent by the client) would actually define the response types. You can see an example of something like this in the server reflection service. However, that is a normal client-to-server sort of RPC. You'd just swap the request and response types (and have the server be the one that initiates requests by sending a "response" message first, and getting a "request" in reply).

For graceful tear-down, the server will simply have to stop using the stream for sending requests, wait for replies to all outstanding operations, and then close the stream/terminate the RPC. When the client is shutting down, it could stop accepting messages from the server (after every one received, send an immediate error message along the lines of "shutting down").

If you want to support out of order execution (e.g. client replies can be sent in different order than server requests were received), then the request and response schemas will need to have an envelope with some sort of request ID, to correlate replies with their original request.

Aside: I've been working on something you may find useful -- a generic mechanism for tunneling gRPC. The tunnel is setup via a gRPC service that provides the same functionality as a low-level gRPC transport. There are a few interesting use cases, but the server-to-client one is the most interesting IMO. If you're curious, you can poke around at the work-in-progress: https://github.com/jhump/grpctunnel. (Unfortunately, I don't know when I'll get around to really finishing this library, but it may have some interesting ideas/code you could use.)

With gRPC it is not possible for the server to initiate contact with the client. However, the client can send an initial rpc to the server and then await their response until the server has the required resource as follows:

using (var call = client.InitialContact(clientID))
{
    var responseStream = call.ResponseStream;
    while (await responseStream.MoveNext()){
        //do something if there is a response
    }
}
Related