客户端解决:
public class ManualFlowControlClient {
private static final Logger logger =
Logger.getLogger(ManualFlowControlClient.class.getName());
public static void main(String[] args) throws InterruptedException {
final CountDownLatch done = new CountDownLatch(1);
// Create a channel and a stub
ManagedChannel channel = ManagedChannelBuilder
.forAddress("localhost", 50051)
.usePlaintext()
.build();
StreamingGreeterGrpc.StreamingGreeterStub stub = StreamingGreeterGrpc.newStub(channel);
// When using manual flow-control and back-pressure on the client, the ClientResponseObserver handles both
// request and response streams.
ClientResponseObserver<HelloRequest, HelloReply> clientResponseObserver =
new ClientResponseObserver<HelloRequest, HelloReply>() {
ClientCallStreamObserver<HelloRequest> requestStream;
@Override
public void beforeStart(final ClientCallStreamObserver<HelloRequest> requestStream) {
this.requestStream = requestStream;
// Set up manual flow control for the response stream. It feels backwards to configure the response
// stream's flow control using the request stream's observer, but this is the way it is.
requestStream.disableAutoInboundFlowControl();
// Set up a back-pressure-aware producer for the request stream. The onReadyHandler will be invoked
// when the consuming side has enough buffer space to receive more messages.
//
// Messages are serialized into a transport-specific transmit buffer. Depending on the size of this buffer,
// MANY messages may be buffered, however, they haven't yet been sent to the server. The server must call
// request() to pull a buffered message from the client.
//
// Note: the onReadyHandler's invocation is serialized on the same thread pool as the incoming
// StreamObserver's onNext(), onError(), and onComplete() handlers. Blocking the onReadyHandler will prevent
// additional messages from being processed by the incoming StreamObserver. The onReadyHandler must return
// in a timely manor or else message processing throughput will suffer.
requestStream.setOnReadyHandler(new Runnable() {
// An iterator is used so we can pause and resume iteration of the request data.