处理长 运行 清理逻辑以响应 Netty channelInactive 事件的正确方法?

Proper way to handle long running cleanup logic in response to Netty channelInactive event?

我有一个 Netty 应用程序可以跟踪已连接的网络套接字连接。当网络套接字断开连接时,我需要执行一些逻辑来清除该连接上存储的数据。我正努力成为一名优秀的 Netty 公民,而不是用这种清理逻辑阻塞事件循环,所以我 运行 将所有内容都放在 CompletableFuture 中。逻辑看起来像这样:

  @Override
  public void channelInactive(ChannelHandlerContext ctx) {
    String connectionId = ctx.channel().id().asLongText();
    LOGGER.info("Web socket disconnected: {}.", connectionId);
    connectionStore
        .deleteConnection(connectionId)
        .thenCompose(
            (connection) → {
              LOGGER.info("Deleted connection {}, publishing event.", connectionId);
              return messageBusPublisher.publish(new DisconnectEvent(connectionId));
            })
        .thenAccept((v) -> LOGGER.info("Done cleaning up connection {}.", connectionId));
  }

这会产生如下日志语句:

2020-02-10 17:47:23,091 [nioEventLoopGroup-6-2] INFO  c.e.WebSocketFrameHandler - Web socket disconnected: acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2.
2020-02-10 17:47:23,091 [nioEventLoopGroup-6-2] INFO  c.e.store.ConnectionStore - Attempting to delete connection for acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2
2020-02-10 17:47:23,092 [nioEventLoopGroup-6-1] INFO  c.e.WebSocketFrameHandler - Web socket disconnected: acde48fffe001122-000080ec-00000003-60f2c3402164ad79-a7e03a19.
2020-02-10 17:47:23,092 [nioEventLoopGroup-6-1] INFO  c.e.store.ConnectionStore - Attempting to delete connection for acde48fffe001122-000080ec-00000003-60f2c3402164ad79-a7e03a19
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-3] INFO  c.e.WebSocketFrameHandler - Web socket disconnected: acde48fffe001122-000080ec-00000005-6962838a219b52e9-e6ceac8b.
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-3] INFO  c.e.store.ConnectionStore - Attempting to delete connection for acde48fffe001122-000080ec-00000005-6962838a219b52e9-e6ceac8b
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-5] INFO  c.e.WebSocketFrameHandler - Web socket disconnected: acde48fffe001122-000080ec-00000007-ccfcc4a5219b57eb-d78fc5f5.
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-4] INFO  c.e.WebSocketFrameHandler - Web socket disconnected: acde48fffe001122-000080ec-00000006-6c933ab1219b554f-2b3cf759.
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-5] INFO  c.e.store.ConnectionStore - Attempting to delete connection for acde48fffe001122-000080ec-00000007-ccfcc4a5219b57eb-d78fc5f5
2020-02-10 17:47:23,093 [nioEventLoopGroup-6-4] INFO  c.e.store.ConnectionStore - Attempting to delete connection for acde48fffe001122-000080ec-00000006-6c933ab1219b554f-2b3cf759
2020-02-10 17:47:23,097 [lettuce-kqueueEventLoop-4-1] INFO  c.e.store.ConnectionStore - Successfully deleted connection for acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2
2020-02-10 17:47:23,102 [lettuce-kqueueEventLoop-4-1] INFO  c.e.WebSocketFrameHandler - Deleted connection acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2, publishing event.
2020-02-10 17:47:23,127 [lettuce-kqueueEventLoop-4-1] INFO  c.e.service.MessageBusPublisher - Attempting to publish message for acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2
2020-02-10 17:47:23,866 [sdk-async-response-0-0] INFO  c.e.service.MessageBusPublisher - Successfully published message for acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2
2020-02-10 17:47:23,866 [sdk-async-response-0-0] INFO  c.e.WebSocketFrameHandler - Done cleaning up connection acde48fffe001122-000080ec-00000004-d86b4b1c219b503a-d8239aa2

我 运行 遇到的问题是,当多次断开连接在短时间内发生时,似乎完整的清理逻辑只是 运行 用于第一个或两个连接,并且除此之外,在处理初始调用之后什么也没有。这意味着连接已从存储中正确删除,但除此之外不会处理任何后续操作。我的假设是,这是因为表示完整调用链的 CompletableFuture 未绑定任何内容,因此当链中的第一个调用完成时,不会执行回调。

我尝试了各种方法,例如使用 ctx.channel().eventLoop().execute(...) 到 运行 清理代码(理论上将执行绑定到通道的事件循环),但我看到了相同的结果。

我的问题是:什么是触发 I/O 绑定任务以响应 Netty 通道事件的适当方法?

正如上面评论中所讨论的,这与我如何处理漫长的 运行 工作无关,而是我的期货缺乏错误处理。

孩子们,请记住始终捕捉未来的异常!