java - 如何在 Netty 中使用多个 ServerBootstrap 对象

标签 java netty nio

我正在尝试使用 Netty (4.0.24) 在一个应用程序(一种主要方法)中创建多个服务器(多个 ServerBootstrap)。我看到了这个问题/答案,但它留下了许多 Unresolved 问题: Netty 4.0 multi port with difference protocol each port 所以这是我的问题: 上面的答案表明我们需要做的就是创建多个 ServerBootstrap 对象并为每个对象绑定(bind)()。但是我看到的大多数针对单个 ServerBootstrap 的代码示例都会调用如下内容:

try {
    b.bind().sync().channel().closeFuture().sync();
}
finally {
    b.shutdown();
}

那么 sync() 调用不会导致 ServerBootstrap b 阻塞吗?那么我们如何为多个 ServerBootstrap 执行此操作呢?如果我们不调用 sync() 会发生什么?同步调用集是否仅用于能够使用 b.shutdown() 正常关闭服务器?如果是这样,有没有办法优雅地关闭多个 ServerBootstrap?

此外,我不明白当我们只调用 bind() 而不调用 sync() 时会发生什么。服务器是否以某种方式继续运行?我们如何优雅地关闭它?

显然,我对这一切的工作原理感到很困惑,遗憾的是,在这方面确实缺乏 Netty 文档。任何帮助将不胜感激。

最佳答案

下面是您引用的示例,并在 sync() 方法上添加了您的问题,这里是一个示例代码:

EventLoopGroup bossGroup = new NioEventLoopGroup(numBossThreads);
EventLoopGroup workerGroup = new NioEventLoopGroup(numWorkerThreads);
ServerBootstrap sb1 = null;
ServerBootstrap sb2 = null;
ServerBootstrap sb3 = null;
Channel ch1 = null;
Channel ch2 = null;
Channel ch3 = null;
try {
    sb1 = new ServerBootstrap();
    sb1.group(bossGroup, workerGroup);
    ...
    ch1 = sb1.bind().sync().channel();

    sb2 = new ServerBootstrap();
    sb2.group(bossGroup, workerGroup);
    ...
    ch2 = sb2.bind().sync().channel();

    sb3 = new ServerBootstrap();
    sb3.group(bossGroup, workerGroup);
    ...
    ch3 = sb3.bind().sync().channel();
} finally {
    // Now waiting for the parent channels (the binded ones) to be closed
    if (ch1 != null) {
        ch1.closeFuture().sync();
    }
    if (b1 != null) {
        b1.shutdownGracefully();
    }
    if (ch2 != null) {
        ch2.closeFuture().sync();
    }
    if (b2 != null) {
        b2.shutdownGracefully();
    }
    if (ch3 != null) {
        ch3.closeFuture().sync();
    }
    if (b3 != null) {
        b3.shutdownGracefully();
    }

现在开始解释(我尝试):

  • bind() 命令创建监听相应的套接字。它立即返回(不阻塞),因此父 channel 可能尚不可用。
  • 第一个sync()命令(bind().sync())等待绑定(bind)完成(如果抛出异常,则直接进行到最后一部分)。在此阶段, channel 已准备就绪,并且可以肯定地监听新连接。
  • channel() 命令获取此监听 channel (父 channel ,尚未连接到任何 channel )。所有客户端都将生成该父 channel 的“子” channel 。
  • 在您的处理程序中,在某个事件发生后,您决定关闭父 channel (不是子 channel ,而是监听和等待新套接字的 channel )。要关闭此操作,只需调用 parentChannel.close()(或从子 channel child.parent().close())。
  • closeFuture() 命令正在获取此关闭事件的 future 。
  • 当这个 future 结束(完成)时,这是最后一个 sync() 命令(closeFuture().sync())将发生的时间。<
  • 父 channel 关闭后,您可以请求正常关闭绑定(bind) channel 。

所以这样做(等待 closeFuture 然后 shutdownGracefully)是关闭所有附加到此 ServerBootstrap 的资源的干净方法。

当然你可以改变一些东西。例如,不是先获取 channel ,而是在您想要在正常关闭之前阻塞时才获取 channel 。

EventLoopGroup bossGroup = new NioEventLoopGroup(numBossThreads);
EventLoopGroup workerGroup = new NioEventLoopGroup(numWorkerThreads);
ServerBootstrap sb1 = null;
ServerBootstrap sb2 = null;
ServerBootstrap sb3 = null;
ChannelFuture cf1 = null;
ChannelFuture cf2 = null;
ChannelFuture cf3 = null;
try {
    sb1 = new ServerBootstrap();
    sb1.group(bossGroup, workerGroup);
    ...
    cf1 = sb1.bind();

    sb2 = new ServerBootstrap();
    sb2.group(bossGroup, workerGroup);
    ...
    cf2 = sb2.bind();

    sb3 = new ServerBootstrap();
    sb3.group(bossGroup, workerGroup);
    ...
    cf3 = sb3.bind();
} finally {
    // Now waiting for the parent channels (the binded ones) to be closed
    if (cf1 != null) {
        cf1.sync().channel().closeFuture().sync();
    }
    if (cf2 != null) {
        c2.sync().channel().closeFuture().sync();
    }
    if (cf3 != null) {
        cf3.sync().channel().closeFuture().sync();
    }
    if (b1 != null) {
        b1.shutdownGracefully();
    }
    if (b2 != null) {
        b2.shutdownGracefully();
    }
    if (b3 != null) {
        b3.shutdownGracefully();
    }

这样您就不会在打开所有 3 个 channel 时完全阻塞,而是在关闭它们之前等待所有 3 个 channel 完成。

最后,如果您不阻塞 bind() 事件然后阻塞 closeFuture() 事件,则由您定义在 之后如何等待code>sbx.bind() 命令和之前关闭 ServerBootstraps。

关于java - 如何在 Netty 中使用多个 ServerBootstrap 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27112084/

相关文章:

java - Spring Boot REST Controller 仅与尾随 "/"匹配

netty - 如何在 Netty 4 中删除拥塞的连接

java - Netty Http Client : how to separate client-start,发送请求,和client-shutdown分为不同的方法

java - 当我添加 ExecutionHandler 时,netty 服务器似乎被阻止了?

java - 读取文件中一行的最快方法

java - Class.getDeclaredMethods 对于没有参数和 void 返回类型的类方法抛出 NoClassDefFoundError

java - 如何获取所有带有@Entity注解的bean?

java - 您可以在 JAX-RS 中全局设置 Jackon 的 Include.NON_NULL 吗?

java - 如何在java中使用SSL实现NIO?

java - redis nio 客户端如何正常工作?