【问题标题】:Channel ManagedChannelImpl was not shut down properlyChannel ManagedChannelImpl 未正确关闭
【发布时间】:2019-12-20 05:56:24
【问题描述】:

如果我按照这两个测试运行,我会得到错误。

第一次测试

@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 SEVERE: ~~~ 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();
}

【问题讨论】:

  • grpcCleanup 是什么?您应该使用InProcessServerBuilder(检查)创建一个服务器,然后在同一个链式调用中添加相应的服务。
  • 已编辑,@Rule public GrpcCleanupRule grpcCleanup = new GrpcCleanupRule();,我是新手,使用示例
  • 我会尝试在@Before 中创建所有这些东西,然后在@After 中停止服务器;无论如何,您正在测试的那些方法不应该负责启动和停止 gRPC 服务器。
  • 使用 GrpcCleanupRule,您不需要 @After@Before 获取 grpc 资源。但第二次测试需要注册它创建的通道。清理规则将调用正常关闭。
  • 第二个测试是在它自己的文件中的某种集成测试(与第一个测试不同的 .java 文件),您能否提供有关如何正确编写这种集成测试的代码。

标签: java grpc grpc-java


【解决方案1】:

嘿,我刚刚使用 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.

【讨论】:

    【解决方案2】:

    我最近在使用 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);
                  
    }
    

    或添加尝试/最终

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-03
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多