问题描述
我正在尝试使用Netty(4.0.24)在一个应用程序(一种主要方法)中创建多个服务器(几个ServerBootstrap).我看到了这个问题/答案,但是却留下了许多未解决的问题:每个端口具有不同协议的Netty 4.0多端口所以这是我的问题:上面的答案表明,我们需要做的就是创建多个ServerBootstrap对象,并将其绑定到每个对象.但是,我在单个ServerBootstrap上看到的大多数代码示例都将调用如下代码:
I am trying to use Netty (4.0.24) to create several servers (several ServerBootstraps) in one application (one main method). I saw this question/answer but it leaves many questions unanswered:Netty 4.0 multi port with difference protocol each portSo here are my questions:The above answer suggests that all we need to do is create multiple ServerBootstrap objects and bind() to each. But most of the code examples I see for a single ServerBootstrap will then call something like this:
try {
b.bind().sync().channel().closeFuture().sync();
}
finally {
b.shutdown();
}
那么sync()调用不会导致ServerBootstrap b阻塞吗?那么我们如何针对多个ServerBootstrap执行此操作?如果不调用sync()会发生什么?同步调用集是否仅能通过b.shutdown()正常关闭服务器?如果是这样,有什么办法可以正常关闭多个ServerBootstrap?
So doesn't the sync() call result in the ServerBootstrap b blocking? So how can we do this for multiple ServerBootstraps? And what happens if we do not call sync()? Is the set of sync calls only for being able to gracefully shutdown the server with b.shutdown()? If so, is there any way to gracefully shutdown multiple ServerBootstraps?
此外,我不了解当我们仅调用bind()而未调用sync()时会发生什么.服务器是否以某种方式保持运行?我们如何优雅地关闭它?
Also, I don't understand what happens when we just call bind() without calling sync(). Does the server somehow keep running? How do we shut it down gracefully?
显然,我对所有这些工作原理都感到困惑,可悲的是,在这方面确实缺少Netty文档.任何帮助将不胜感激.
Obviously I'm pretty confused about how all this works, and sadly Netty documentation is really lacking in this regard. Any help would be greatly appreciated.
推荐答案
以下是您引用的示例,并在sync()
方法上添加了问题,下面是示例代码:
Following example you referenced and adding your question on sync()
method, here an example code:
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();
}
现在,在解释上(我尝试):
So now on the explanations (I try):
-
bind()
命令创建侦听的对应套接字.它会立即返回(不阻塞),因此父频道可能还不可用. - 第一个
sync()
命令(bind().sync()
)等待绑定完成(如果引发异常,则它直接进入最后部分).在此阶段,频道已准备就绪,可以肯定地侦听新的连接. -
channel()
命令获取此侦听通道(父通道,尚未连接).所有客户都会为此父级客户生成一个子级"渠道. - 在处理程序中,在发生某些事件之后,您决定关闭父通道(不是子通道,而是监听和等待新套接字的那个通道).要关闭此窗口,只需调用
parentChannel.close()
(或从子通道child.parent().close()
). -
closeFuture()
命令在此关闭事件中发挥了作用. - 这个未来结束(完成)时,这是最后一个
sync()
命令(closeFuture().sync()
)发生的时间. - 父频道关闭后,您可以要求正常关闭绑定的频道.
- The
bind()
command creates the listening corresponding socket. It returns immediately (not blocking) so the parent channel might not be yet available. - The first
sync()
command (bind().sync()
) waits for the binding to be done (if an exception is raised, then it goes directly to the finally part). At this stage, the channel is ready and listening for new connections for sure. - The
channel()
command gets this listening channel (the parent one, connected to no one yet). All clients will generate a "child" channel of this parent one. - In you handler, after some event, you decide to close the parent channel (not the child one, but the one listening and waiting for new socket). To do this close, just call
parentChannel.close()
(or from a child channelchild.parent().close()
). - The
closeFuture()
command is getting the future on this closing event. - When this future is over (done), this is when the last
sync()
command (closeFuture().sync()
) will take place. - Once the parent channel is closed, you can ask for a gracefully shutdown of the binded channel.
因此,执行此方法(等待closeFuture然后正常关闭shutdown)是关闭所有附加到此ServerBootstrap的资源的干净方法.
So doing this way (waiting for the closeFuture then shutdownGracefully) is a clean way to shutdown all resources attached to this ServerBootstrap.
当然,您可以更改一些东西.例如,当您要在正常关闭之前阻塞时,不要先获取频道,而要稍后获取.
Of course you can change a bit the things. For instance, not getting the channel first but only later when you want to block before gracefully shutdown.
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个通道之前等待它们完成.
This way you don't block at all while opening all 3 channels, but then wait for all 3 to be done before shutdown them.
最后,如果您没有在bind()
事件上然后在closeFuture()
事件上进行阻塞,则由您决定如何在sbx.bind()
命令之后以及在关闭ServerBootstrap之前等待.
Finally, if you don't block on bind()
event then on closeFuture()
event, it's up to you to define how you will wait after the sbx.bind()
commands and before to shutdown the ServerBootstraps.
这篇关于如何在Netty中使用多个ServerBootstrap对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!