2017-04-14 338 views
3

我正在使用GRPC-Java 1.1.2。在一個活躍的GRPC會議中,我打開了一些雙向流。當客戶端斷開連接時,是否有辦法從客戶端清除它們?當我嘗試斷開連接時,我運行以下查找固定次數然後斷開連接,但是我可以在服務器端看到以下錯誤(不確定它是否由另一個問題引起):清理乾淨地從客戶端關閉GRPC-Java中的所有開放流

斷開連接客戶

while (!channel.awaitTermination(3, TimeUnit.SECONDS)) { 
// check for upper bound and break if so 
} 
channel.shutdown().awaitTermination(3, TimeUnit.SECONDS); 

服務器上

E0414 11:26:48.787276000 140735121084416 ssl_transport_security.c:439] SSL_read returned 0 unexpectedly. 
E0414 11:26:48.787345000 140735121084416 secure_endpoint.c:185]  Decryption error: TSI_INTERNAL_ERROR 

回答

3

錯誤如果使用shutdownNow()它會更積極地關閉RPC流ÿ你有。此外,撥打awaitTermination()之前,您需要撥打shutdown()shutdownNow()

也就是說,更好的解決方案是在關閉通道之前優雅地結束所有的RPC。

+0

會盡快恢復 - 謝謝 –

1

如果要關閉來自客戶端的gRPC(服務器端或雙向)流,則必須將rpc呼叫與io.grpc包中的Context.CancellableContext附加在一起。

假設你有一個RPC:

service Messaging { 
    rpc Listen (ListenRequest) returns (stream Message) {} 
} 

在客戶端,你會處理這樣的:

public class Messaging { 
    private Context.CancellableContext mListenContext; 

    private MessagingGrpc.MessagingStub getMessagingAsyncStub() { 
    /* return your async stub */ 
    } 

    public void listen(final ListenRequest listenRequest, final StreamObserver<Message> messageStream) { 

     Runnable listenRunnable = new Runnable() { 
      @Override 
      public void run() { 
       Messaging.this.getMessagingAsyncStub().listen(listenRequest, messageStream); 
      } 

     if (mListenContext != null && !mListenContext.isCancelled()) { 
      Log.d(TAG, "listen: already listening"); 
      return; 
     } 

     mListenContext = Context.current().withCancellation(); 
     mListenContext.run(listenRunnable); 
    } 

    public void cancelListen() { 
     if (mListenContext != null) { 
      mListenContext.cancel(null); 
      mListenContext = null; 
     } 
    } 
} 

調用cancelListen()將模擬錯誤, '已取消',則連接會被關閉,並且您的StreamObserver<Message> messageStreamonError將被調用並顯示可丟棄的消息:'CANCELED'。