当前位置: 首页 > 面试题库 >

如何在Netty通道处理程序中安全地执行阻止操作?

万勇
2023-03-14
问题内容

我正在构建一个基于Netty的小型应用程序,该应用程序通过套接字连接(即telnet / ssh)执行I /
O操作。我正在用Netty的ServerBootstrap类启动我的套接字服务器,给它:

  1. 类型的事件循环NioEventLoopGroup(即不应接受阻塞操作的共享线程池)。

  2. 一个类型的通道NioServerSocketChannel(我相信这必须与上面的#1相对应)。

  3. 一个非常简单的管道,带有可扩展的通道处理程序ChannelInboundHandlerAdapter

channelRead(...)每当从客户端套接字连接接收到命令字符串时,都会调用我的处理程序的方法,并根据命令返回一些响应字符串。

对于不涉及阻塞操作的命令,一切都很好。但是,有些命令现在需要从数据库读取或写入。这些JDBC调用本质上将受到阻塞……尽管我 可以
使用CompletableFuture(或其他方法)在单独的线程中处理它们。

但是,即使我通过在单独的线程中执行阻止操作来“自行完成异步”,我也不知道如何将那些产生的线程的结果重新连接回主线程中的Netty通道处理程序。

我看到ChannelHandlerContext该类具有以下方法:

ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);

…作为我目前正在使用的替代方案:

ChannelFuture writeAndFlush(Object msg);

但是我找不到任何说明如何ChannelPromise在这种用例中使用这种类型的文档或指南(甚至是有用的Javadocs)。顾名思义,它 可能
相关,但可能无关。毕竟,该writeAndFlush方法仍然将传出消息作为其第一个参数……因此,如果您需要将其结果保存在第一个参数中,那么将阻塞操作填充到“承诺”第二个参数中有什么用呢?参数?

这里正确的路是什么?有什么方法可以处理单独线程中的阻塞操作,以使Netty
NioEventLoopGroup不会阻塞?还是这不是Netty的工作原理,如果需要支持阻塞,应该使用不同的事件循环实现(即为每个客户端套接字连接生成单独的线程)。


问题答案:

如果Netty中的操作需要较长的时间才能完成或正在阻塞,则建议在中执行该操作,handler that uses a separate ExecutorGroup以免主EventLoop线程被阻塞。

您可以在管道创建期间指定它。

引用从ChannelPipeline
javadoc
使用执行程序组进行数据库操作的示例

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());


 类似资料:
  • 问题内容: 我有一棵divs树: 在div上单击时,将使其子级不可见-即单击“ a”将使“ b”和“ c”不可见。 问题是:单击“ b”将调用“ a”的单击,并使“ b”和“ c”不可见。如何使用jQuery禁用对“ a”的点击? 谢谢 问题答案: 您可以为孩子添加一个处理程序,以防止click事件蔓延: 这样一来,点击不会传播到。都不会单击以转到,因此也不会。

  • 我正在尝试使用动态ChannelHandler管道实现Netty 4. X。正如人们建议的“出于性能考虑,在运行时使用调用而不是管道修改”,我实现了一个Server、一个RouterInoundHander和一个Client来测试这个理论。但它不起作用。这是我的代码 计算机网络服务器 RouterInboundHandler 和客户 如代码所示,在Channel的连接初始化阶段创建了Channel

  • 如另一个问题中所述,当使用Undertow时,所有处理都应该在专用的工作线程池中完成,如下所示: 我知道可用于显式地告诉Undertow在专用的线程池中调度请求以阻止请求。我们可以通过将包装在实例中来修改上面的示例,如下所示: 调用此方法将exchange置于阻塞模式,并创建一个BlockingHttpExchange对象来存储流。当交换处于阻塞模式时,输入流方法变得可用,除了阻塞和非阻塞模式之间

  • 我试图通过“网络在行动”这本书来掌握网络概念。 在我看来,有几个概念解释得不太好或太模糊。因此,我想我会来这里就这些话题做一些明确的解释。 渠道管道: 所以我有一个这样的渠道管道: 对于channelInitializer,从概念上讲,我会假设该过程将按以下顺序进行:

  • 消费者是一个spring集成项目,它从消息队列中消费并执行大量处理。我使用Executor通道并行处理消息,然后流通过一些公共处理程序类。 请在下面的代码片段中找到- -我们从EMS队列接收消息并将其发送到路由器 -基于以下消息的id:“特定ExecutorChannel实例配置了一个单线程执行器。每个ExecutorChannel都将是它的专用执行器,只有一个线程。 -所有ExecutorCha

  • 我正在学习Netty并制作一个通过TCP发送对象的简单应用程序的原型。我的问题是,当我用我的消息从服务器端调用时,它似乎没有到达管道中的处理程序。当我从客户端向服务器发送消息时,它按预期工作。 这是代码。 服务器: 双工通道处理程序: 最后是编码器(解码器类似): 客户端: 和处理程序: 当我通过服务器端的控制台发送消息时,我得到了输出: 因此,看起来似乎在客户端发送了消息,但没有收到任何消息。