Grpc-java: How to cancel a GRPC Server streaming call

Created on 13 Jun 2017  路  13Comments  路  Source: grpc/grpc-java

I made a Call to server. The server streams. I want to cancel the call from client.

How to cancel? No Method to cancel a call.

Most helpful comment

@varshanbp wants to shut down the stream from the client side, this example shuts it down from the server side @fanminshi

All 13 comments

@varshanbp I think you need to call onCompleted() of the streamObserver from client to terminate the stream call.
http://www.grpc.io/docs/tutorials/basic/java.html

@fanminshi I use "Server-side streaming RPC". I want to close the channel from client. If I shutdown channel from client, it throws error in Server and keeps returning value to closed channel. How to solve this problem?

I want to close a channel from Client properly.

@varshanbp wants to shut down the stream from the client side, this example shuts it down from the server side @fanminshi

@conorgriffin oops. wrong example. I meant to show this one.

you probably don't want to kill channel right away. maybe follow the example here to properly shutdown channel.

  public void shutdown() throws InterruptedException {
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
  }

https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java#L62-L64

@varshanbp In the future, this kind of question would be better posted on Stack Overflow or the mailing list.

To answer your question: You can cancel a call on the client by calling onError(Status.CANCELED). The actual error doesn't matter too much since it won't actually be put on the wire. gRPC will send an RST_STREAM packet which will show up on the server's onError handler.

If you want a more graceful shutdown, you can modify your streaming RPC to just make onCompleted interpreted as a cancellation, which will make things close down more gracefully.

Note that ManagedChannel.shutdown won't end any in progress RPCs. It just says that no new RPCs can be started, and that once the number of active RPCs is 0, the channel will close all connections. If you want a more active shutdown, you can use shutdownNow, which cancels all streams too.

@carl-mastrangelo, the client can't call onError(Status) on server-streaming calls, since it doesn't have a request StreamObserver. Today, the only way to cancel the call is by cancelling the Context. So you'd need to create a CancellableContext before the call and cancel it when necessary or when the call is complete.

It'd be a good API to add to ClientCallStreamObserver.

@ejona86 another way to cancel server-streaming calls or unary calls from client side is using an interceptor, and call ClientCall.cancel

We've been trying to find a solution for canceling unary calls a few months ago. We found that unary calls are uncancelable by design ("unary calls should provide enough information to the server to make the server cancel properly" - sorry, can't find the quote now as I'm on mobile, but it comes from grpc devs).

Since then we've been marking all our cancelable unary calls as streaming (while documenting the intent).

We found that unary calls are uncancelable by design

No, they should be cancellable. It is important that they can be cancelled on-demand by the client. That is non-negotiable (it's been argued before), so if you'd like me to argue with another dev I can :)

Since then we've been marking all our cancelable unary calls as streaming (while documenting the intent).

Yeah, that doesn't really help anyone. Unary RPCs are much easier to use in most languages.

Yeah, you're right, sorry. I found the quote: https://github.com/grpc/grpc/issues/8023#issuecomment-245402978. Apparently I misread that / misremember that.

In general, the assumption of a server-only streaming call is that the initial message from the client contains enough information for the server to know when to stop.

If the client unexpectedly has to stop the stream in the middle, you can cancel the call (call.cancel()). Note that this will terminate the call with a CANCELLED status.

which basically says what you're saying. And yet at the time of testing this (in February) we did not find a working solution in Java/node.js. I'll try again with the context stuff you mentioned. Still this sucks more than it should.

Thanks for clearing this up, it actually makes gRPC looks good to me again. We wrote a whole machinery around these cancallable server-streaming calls, and I'm looking forward to deleting it all.

_(EDIT: Removed some wrong assumptions. I don't remember things correctly after 5 months of not working with this anymore.)_

I'll try again with the context stuff you mentioned. Still this sucks more than it should.

Agreed. But on the bright side #3115 is merged and will be available in 1.6. Also, using ClientCall directly isn't _that_ bad and isn't too different than the StreamObserver, so that's another short-term option.

It's in the Context documentation, but when making your own CancellableContext, make sure you cancel it when done with it (in the success case).

Am i right, that there is no way to cancel using the auto-generated stubs (Java) !?
I would have to stop using the stubs and invoke getChannel().newCall by myself ?

@jzillmann you can use io.grpc.Context to cancel any stub type. For blocking you can interrupt the thread; for future you can cancel the future; for async you can use ClientCallStreamObserver.cancel() by casting the returned StreamObserver to ClientCallStreamObserver or implementing having your passed-in StreamObserver implement ClientResponseObserver.

Was this page helpful?
0 / 5 - 0 ratings