处理长 运行 清理逻辑以响应 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 通道事件的适当方法?
正如上面评论中所讨论的,这与我如何处理漫长的 运行 工作无关,而是我的期货缺乏错误处理。
孩子们,请记住始终捕捉未来的异常!
我有一个 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 通道事件的适当方法?
正如上面评论中所讨论的,这与我如何处理漫长的 运行 工作无关,而是我的期货缺乏错误处理。
孩子们,请记住始终捕捉未来的异常!