java - 如何在 Netty channel 处理程序中安全地执行阻塞操作?

标签 java multithreading asynchronous netty nio

我正在构建一个基于 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/

    相关文章:

    c++ - 异步 ReadFile() 导致运行时错误?

    javascript - 如何在 Node.js 中停止异步执行

    java - 没有 @EnableAspectJAutoProxy,Spring AOP 能工作吗?

    java - java 虚拟机崩溃时,可以将 hs_err_pid*.log 写入特定目录(不同于类目录)吗?

    java - Jersey 客户端在 XML 反序列化期间未设置字段

    java - 安卓工作室 : "Gradle sync failed: Could not run JVM from the selected JDK."

    JAVA实时控制台-控制线程

    java - 等待计算值(或超时)的高效并发数据结构

    java - 手机锁定一段时间后,appWidget 停止更新/工作

    javascript - 我需要在嵌套的 require 调用中列出多少个依赖项?