多个工作者事件循环组
Multiple worker event loop groups
我正在尝试使用 netty 4.1.x 编写一个预期托管数千个持久连接 (TLS) 的 TCP 服务器。在性能测试期间,我们观察到,如果有几千个连接到服务器,然后我们又突发了另外几千个连接,这些新的 SSL 握手会使工作线程长时间忙碌,这会导致现有连接开始超时。
在 Internet 上所有可用的 Netty 示例中,我看到服务器是这样引导的:
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup) ...
我想知道是否可以使用两个工作组而不是一个。所以,我打算做的是让 workerGroup(如上所示)处理初始握手,一旦完成,我从该组中注销 Channel 并将其注册到辅助组(参见下面的示例代码)。
class SwitchToSecondaryGroupHandler extends ChannelInboundHandlerAdapter {
private final EventLoopGroup secondaryEventLoopGroup;
public SwitchToSecondaryGroupHandler(EventLoopGroup eventLoopGroup) {
this.secondaryEventLoopGroup = eventLoopGroup;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.pipeline().remove(this);
ChannelFuture future = ctx.channel().deregister();
future.addListener((f) -> {
if (f.isSuccess()) {
ChannelFuture registerFuture = secondaryEventLoopGroup.register(ctx.channel());
registerFuture.addListener((e) -> {
ctx.fireChannelRead(msg);
});
}
});
}
}
此处理程序将立即添加到 SslHandler 之后。它可能不必在通道读取之后完成,也可以在写入之前完成。
这样次要组可以继续为现有连接提供服务,并且任何新连接的突发都不会影响它们。在我使用带有 StringEncoder/Decoder 的独立程序进行的测试中,它似乎有效。
这种方法有什么潜在的问题吗?我所说的问题是指 netty 本身的运作。
理论上这是可行的,但重新注册频道是一种 "hacky" 业务,这也可能导致我们在某些时候不再支持 netty 的情况。这里的问题在于,当通道从一个线程移动到另一个线程时,要确保事物的可见性和执行的正确性。
我很想看看您在此处描述的问题的探查器快照,因为这显然不是我所期望的。你能不能打开一个包含所有信息的 netty issue 并在那里附上探查器快照。谢谢!
我正在尝试使用 netty 4.1.x 编写一个预期托管数千个持久连接 (TLS) 的 TCP 服务器。在性能测试期间,我们观察到,如果有几千个连接到服务器,然后我们又突发了另外几千个连接,这些新的 SSL 握手会使工作线程长时间忙碌,这会导致现有连接开始超时。 在 Internet 上所有可用的 Netty 示例中,我看到服务器是这样引导的:
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup) ...
我想知道是否可以使用两个工作组而不是一个。所以,我打算做的是让 workerGroup(如上所示)处理初始握手,一旦完成,我从该组中注销 Channel 并将其注册到辅助组(参见下面的示例代码)。
class SwitchToSecondaryGroupHandler extends ChannelInboundHandlerAdapter {
private final EventLoopGroup secondaryEventLoopGroup;
public SwitchToSecondaryGroupHandler(EventLoopGroup eventLoopGroup) {
this.secondaryEventLoopGroup = eventLoopGroup;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.pipeline().remove(this);
ChannelFuture future = ctx.channel().deregister();
future.addListener((f) -> {
if (f.isSuccess()) {
ChannelFuture registerFuture = secondaryEventLoopGroup.register(ctx.channel());
registerFuture.addListener((e) -> {
ctx.fireChannelRead(msg);
});
}
});
}
}
此处理程序将立即添加到 SslHandler 之后。它可能不必在通道读取之后完成,也可以在写入之前完成。 这样次要组可以继续为现有连接提供服务,并且任何新连接的突发都不会影响它们。在我使用带有 StringEncoder/Decoder 的独立程序进行的测试中,它似乎有效。
这种方法有什么潜在的问题吗?我所说的问题是指 netty 本身的运作。
理论上这是可行的,但重新注册频道是一种 "hacky" 业务,这也可能导致我们在某些时候不再支持 netty 的情况。这里的问题在于,当通道从一个线程移动到另一个线程时,要确保事物的可见性和执行的正确性。
我很想看看您在此处描述的问题的探查器快照,因为这显然不是我所期望的。你能不能打开一个包含所有信息的 netty issue 并在那里附上探查器快照。谢谢!