频道ManagedChannelImpl未正确关闭

时间:2019-08-13 16:20:37

标签: java grpc grpc-java

如果我遵循这两个测试,则会收到错误消息。

第一次测试

@Rule
public GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();

@Test
public void findAll() throws Exception {
    // Generate a unique in-process server name.
    String serverName = InProcessServerBuilder.generateName();

    // Create a server, add service, start, and register for automatic graceful shutdown.
    grpcCleanup.register(InProcessServerBuilder
            .forName(serverName)
            .directExecutor()
            .addService(new Data(mockMongoDatabase))
            .build()
            .start());

    // Create a client channel and register for automatic graceful shutdown.
    RoleServiceGrpc.RoleServiceBlockingStub stub = RoleServiceGrpc.newBlockingStub(
            grpcCleanup.register(InProcessChannelBuilder
                    .forName(serverName)
                    .directExecutor()
                    .build()));

    RoleOuter.Response response = stub.findAll(Empty.getDefaultInstance());
    assertNotNull(response);
}

第二次测试

@Test
public void testFindAll() {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8081)
            .usePlaintext()
            .build();

    RoleServiceGrpc.RoleServiceBlockingStub stub = RoleServiceGrpc.newBlockingStub(channel);
    RoleOuter.Response response = stub.findAll(Empty.newBuilder().build());
    assertNotNull(response);
}
  

io.grpc.internal.ManagedChannelOrphanWrapper $ ManagedChannelReference   cleanQueue严重:〜Channel ManagedChannelImpl {logId = 1,   target = localhost:8081}未正确关闭!!! 〜       确保调用shutdown()/ shutdownNow()并等到awaitTermination()返回true。

     

java.lang.RuntimeException:ManagedChannel分配站点   在io.grpc.internal.ManagedChannelOrphanWrapper $ ManagedChannelReference。(ManagedChannelOrphanWrapper.java:94)

如果我注释掉其中之一,则没有错误,虽然单元测试通过了,但是如果两者一起运行,则会引发异常。

修改

根据建议。

@Test
public void testFindAll() {
    ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", 8081)
            .usePlaintext()
            .build();

    RoleServiceGrpc.RoleServiceBlockingStub stub = RoleServiceGrpc.newBlockingStub(channel);
    RoleOuter.Response response = stub.findAll(Empty.newBuilder().build());
    assertNotNull(response);

    channel.shutdown();
}

2 个答案:

答案 0 :(得分:0)

嘿,我刚刚在Dialogflow V2 Java SDK中遇到了类似的问题

 Oct 19, 2019 4:12:23 PM io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference cleanQueue
SEVERE: *~*~*~ Channel ManagedChannelImpl{logId=41, target=dialogflow.googleapis.com:443} was not shutdown properly!!! ~*~*~*
    Make sure to call shutdown()/shutdownNow() and wait until awaitTermination() returns true.

此外,拥有庞大的客户群,我们开始遇到out of memory unable to create native thread错误。

在执行了许多调试操作并使用了Visual VM线程监视之后,我终于发现问题是由于SessionsClient没有关闭。因此,我使用了随附的代码块来解决该问题。经过测试之后,我终于能够释放所有使用的线程,并且前面提到的错误也得到解决。

SessionsClient sessionsClient = null;
QueryResult queryResult = null;

try {
    SessionsSettings.Builder settingsBuilder = SessionsSettings.newBuilder();
    SessionsSettings sessionsSettings = settingsBuilder
            .setCredentialsProvider(FixedCredentialsProvider.create(credentials)).build();
    sessionsClient = SessionsClient.create(sessionsSettings);
    SessionName session = SessionName.of(projectId, senderId);
    com.google.cloud.dialogflow.v2.TextInput.Builder textInput = TextInput.newBuilder().setText(message)
            .setLanguageCode(languageCode);
    QueryInput queryInput = QueryInput.newBuilder().setText(textInput).build();

    DetectIntentResponse response = sessionsClient.detectIntent(session, queryInput);

    queryResult = response.getQueryResult();
} catch (Exception e) {
    e.printStackTrace();
}
finally {
    sessionsClient.close();
}

The shorter values on the graph highlights the use of client.close(). Without that the threads were stuck in Parking State.

答案 1 :(得分:0)

我最近在使用 Google 云任务 API 时遇到了类似的问题。

Channel ManagedChannelImpl{logId=5, target=cloudtasks.googleapis.com:443} was 
not shutdown properly!!! ~*~*~* (ManagedChannelOrphanWrapper.java:159)
Make sure to call shutdown()/shutdownNow() and wait until awaitTermination() returns true.

在这种情况下,CloudTasksClient 对象实现了 AutoCloseable,我们应该在它完成后调用它的 .close() 方法。

我们可以使用像这样的 try 块,它会在完成后自动关闭。

   try( CloudTasksClient client = CloudTasksClient.create()){
               CloudTaskQueue taskQueue = new CloudTaskQueue(client);
              
}

或添加 try/finally

 CloudTasksClient client =null;
          try{
                client = CloudTasksClient.create() ;
                CloudTaskQueue taskQueue = new CloudTaskQueue(client);
           } catch (IOException e) {
                e.printStackTrace();
            } finally {
                client.close();
         }