我试图使用Netty(4.0.24)在一个应用程序中创建几个服务器(几个ServerBootstraps)(一个主要方法).我看到了这个问题/答案,但它留下了许多未回答的问题: Netty 4.0多端口,每个端口都有差异协议 所以这里是我的问题:上面的答案表明我们需要做的就是创建多个ServerBootstrap对象并将bind()分别创建.但是我看到的单个ServerBootstrap的大多数代码示例都会调用这样的代码:
try { b.bind().sync().channel().closeFuture().sync(); } finally { b.shutdown(); }
那么ServerBootstrap b阻塞中的sync()调用结果不是吗?那么我们如何才能为多个ServerBootstraps做到这一点?如果我们不调用sync()会发生什么?同步调用集是否只能通过b.shutdown()正常关闭服务器?如果是这样,有没有办法优雅地关闭多个ServerBootstraps?
另外,我不明白当我们只调用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()
命令创建侦听对应的套接字.它立即返回(不阻塞),因此父通道可能尚未可用.
第一个sync()
命令(bind().sync()
)等待绑定完成(如果引发异常,则直接转到finally部分).在此阶段,通道已准备就绪,并确保侦听新连接.
该channel()
命令获取此侦听通道(父通道,尚未连接到任何人).所有客户端都将生成此父级的"子"通道.
在您的处理程序中,在某个事件之后,您决定关闭父通道(不是子通道,而是侦听并等待新套接字的通道).要做到这一点,只需打电话parentChannel.close()
(或从儿童频道child.parent().close()
).
该closeFuture()
命令是关闭此事件的未来.
当这个未来结束(完成)时,这是最后一个sync()
命令(closeFuture().sync()
)发生的时间.
关闭父通道后,您可以要求正常关闭绑定通道.
所以这样做(等待closeFuture然后shutdownGracefully)是一种干净的方法来关闭附加到这个ServerBootstrap的所有资源.
当然你可以改变一些事情.例如,没有先获取通道,但只有在优先关闭之前要阻塞时才能获得通道.
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个通道时根本不会阻塞,但是在关闭它们之前等待所有3个通道完成.
最后,如果您没有阻止bind()
事件然后在closeFuture()
事件上,sbx.bind()
则由您来定义在命令之后和关闭ServerBootstraps之前等待的方式.