【问题标题】:How can I use an EventExecutorGroup with an NioDatagramChannel in Netty?如何在 Netty 中使用带有 NioDatagramChannel 的 EventExecutorGroup?
【发布时间】:2015-05-25 10:50:54
【问题描述】:

我是 Netty 的新手,但我最近与 NIO 合作了一段时间。 我正在构建一个 UDP 服务器,从我尝试过的示例看来,与 NioServerSocketChannel.class 不同,当您使用 NioDatagramChannel.class 时,您无法分配 EventLoopGroup workerGroup 来处理数据报。已被套接字接受。我的代码基于 Netty QuoteOfTheMoment server 示例,如下所示:

public class PositionServer {

    int port;

    public PositionServer(int port) {
        this.port = port;
        System.out.println("Port set to " + this.port);
    }

    public void run() {
        EventLoopGroup bossGroup = new NioEventLoopGroup();

        try {

            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(bossGroup).channel(NioDatagramChannel.class)
            .handler(new PositionServerHandler());

            System.out.println("Binding to port " + port);
            bootstrap.bind(port).sync().channel().closeFuture().await();

        } catch (InterruptedException e) {
            bossGroup.shutdownGracefully();
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {

        new PositionServer(4000).run();

    }

}

这工作得很好,现在PositionServerHandler 只是将消息输出到控制台。

我想将消息推送到数据库中,它们是 JSON 字符串,所以我想先将它们转换为 JSON。我不想在bossGroup 中执行此操作,因为它会阻塞数据库访问和 JSON 处理。但我看不到添加workerGroup 的明显方法。

谷歌搜索也没有透露太多信息,除了我的workerGroup 在这种情况下可能应该是EventExecutorGroup 而不是EventLoopGroup,但我什至不能 100% 确定这一点。

在 NIO 中,我将有两个线程池,并且我会使用某种队列,一个线程池会将字符串推送到队列中,另一个将从队列中获取字符串,将它们转换为 JSON 对象并推送他们到数据库。

我可以在 Netty 中做类似的事情吗?

在这种情况下,我的PositionServerHandler.class 将在构造函数中接受一个队列,并将整个DatagramPackets 或消息内容推送给它,然后让另一个EventLoopGroup/EventExecutorGroup 接收这些消息并推送它们到数据库。 似乎 ServerBootstrap 不处理 NioDatagramChannels 出于某种原因,这对我来说没有意义。

这可行吗?我是否缺少一些明显的解决方案?

【问题讨论】:

    标签: java netty nio datagram


    【解决方案1】:

    我可以在 Netty 中做类似的事情吗?

    是的。但首先要澄清术语。在典型的 TCP 服务器示例中,“boss 组”是 TCP 接受的事件循环组。 “工作组”是 TCP 接收的事件循环组。由于 UDP 套接字不“接受”,但它们确实接收,所以区分老板组和工作组是没有意义的,在引用的示例中,变量只是称为“组”。它执行与典型 TCP 服务器中的“工作组”相同的功能,即处理传入的数据。

    请记住,单个 NioEventLoopGroup 包含一个线程池,可以配置为具有任意数量的线程。

    在 NIO 中,我会有两个线程池,并且我会使用某种队列...

    您可以使用相同的设计。毕竟你还在使用 NIO——你只需要 Netty 来帮助你。 NioEventLoop “worker”组是你的“第一个”线程池,它将字符串推送到队列中。使用标准 Java API 或使用未附加到任何通道的第二个 netty 事件循环组,以任何您想要的方式创建您的第二个线程池。其他一切都保持不变。

    【讨论】:

    • 太棒了!我仍然不明白为什么有一个工作组与 UDP 无关,这是因为它是无状态的吗?是否意味着您可以在该线程中继续工作,因为不可能接收到额外的数据?如果没有,那么为什么没有像 TCP 套接字那样的 bossGroups 和 workerGroups。如果我每秒接收 1000 个 UDP 数据包,那么拥有 bossGroup 和 workerGroup 是否没有意义?我的意思是,这基本上就是我用我的线程池和队列再次制作的东西,对吧?
    • 对不起,我不清楚。您的服务器将有一个工作组。我的意思是,在 TCP 中,老板组和工人组之间的区别并不适用。我已经更新了答案,希望能澄清一下。
    • 您可能想提到SO_REUSEPORT,它在 epoll 传输中可用,它使用户能够以多线程方式服务单个 UDP 端口。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-13
    • 2012-02-29
    相关资源
    最近更新 更多