我正在构建一个基于 Netty 的小型应用程序,它通过套接字连接(即 telnet/ssh)执行 I/O 操作。我正在使用 Netty 的 ServerBootstrap
启动我的套接字服务器类,给它:
NioEventLoopGroup
类型的事件循环(即不应受到阻塞操作的共享线程池)。 NioServerSocketChannel
的 channel (我相信这是与上面的#1 对应所必需的)。 ChannelInboundHandlerAdapter
的 channel 处理程序. 我的经纪人
channelRead(...)
每当从客户端套接字连接接收到命令字符串时都会调用方法,并根据命令返回一些响应字符串。对于不涉及阻塞操作的命令,一切都很好。但是,我现在需要从数据库中读取或写入一些命令。那些 JDBC 调用本质上会阻塞...虽然我可以使用
CompletableFuture
(或其他)在单独的线程中处理它们。但是,即使我通过在单独的线程中执行阻塞操作来“滚动我自己的异步”,我也不确定如何将这些产生的线程的结果重新连接回主线程中的 Netty channel 处理程序。
我看到
ChannelHandlerContext
类有如下方法:ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);
...作为我目前使用的替代品:
ChannelFuture writeAndFlush(Object msg);
但是我找不到任何文档或指南(甚至有用的 Javadoc)来解释如何使用此
ChannelPromise
在这个用例中输入。它的名字表明它可能是相关的,但也可能不是。毕竟,writeAndFlush
方法仍然将传出消息作为它的第一个参数......那么,如果您需要第一个参数的结果已经在手上,那么将您的阻塞操作填充到“ promise ”第二个参数中会有什么好处?这里的正确轨道是什么?有没有办法在单独的线程中处理阻塞操作,以便Netty的
NioEventLoopGroup
不阻塞?或者这根本不是 Netty 的工作方式,如果您需要支持阻塞,您应该使用不同的事件循环实现(即为每个客户端套接字连接生成一个单独的线程)?
最佳答案
如果 Netty 中的操作需要更长的时间才能完成或被阻塞,建议在 handler that uses a separate ExecutorGroup
中执行该操作。这样主 EventLoop 线程就不会被阻塞。
您可以在管道创建期间指定。
引用ChannelPipeline javadoc中使用executor group进行DB操作的例子
static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
...
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
// Tell the pipeline to run MyBusinessLogicHandler's event handler methods
// in a different thread than an I/O thread so that the I/O thread is not blocked by
// a time-consuming task.
// If your business logic is fully asynchronous or finished very quickly, you don't
// need to specify a group.
pipeline.addLast(group, "handler", new MyBusinessLogicHandler());
关于java - 如何在 Netty channel 处理程序中安全地执行阻塞操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49133447/