[英]How to close a channel gracefully before ssl handshake in Netty?
I'm adding a throttling feature in my application, which needs to close a channel before the SSL handshake to mitigate CPU usage when the incoming request rate exceeds the threshold.我在我的应用程序中添加了一个限制功能,当传入的请求率超过阈值时,它需要在 SSL 握手之前关闭通道以减少 CPU 使用率。 Now I use Netty SslHandler
with server mode to do the handshake.现在我使用 Netty SslHandler
和服务器模式来进行握手。 My current implementation is adding a ChannelInboundHandlerAdapter
before the SslHandler
and rewrite the channelActive
method:我当前的实现是在SslHandler
之前添加一个ChannelInboundHandlerAdapter
并重写channelActive
方法:
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
if (!limiter.tryAcquire()) {
ctx.close();
return;
}
ctx.pipeline().remove(this);
ctx.fireChannelActive();
}
In this way the channel can be closed when it becomes active.通过这种方式,通道可以在变为活动状态时关闭。 However, I will receive SslHandshakeCompletionEvent
with handshake failure.但是,我会在握手失败时收到SslHandshakeCompletionEvent
。 I read the source code of Netty SslHandler
.我阅读了 Netty SslHandler
的源代码。 It will set handshake failure in channelInactive
method when the channelInactive event is triggered.当 channelInactive 事件被触发时,它会在channelInactive
方法中设置握手失败。 So I wonder whether there is a better way to close the channel without firing the handshake failure event, since the handshake process has not started when my throttling close the channel.所以我想知道是否有更好的方法来关闭通道而不触发握手失败事件,因为当我的节流关闭通道时握手过程还没有开始。
You're attacking the problem at the wrong end.你在错误的一端解决问题。 The idea is not to close channels that are being accepted too quickly, but to not accept them too quickly, which will be done in the accept handler, not the channel handler.这个想法不是关闭太快被接受的通道,而是不要太快接受它们,这将在接受处理程序中完成,而不是在通道处理程序中完成。
Your approach is almost right, however, it would be correct to override channelRegistered
method instead of channelActive
.你的做法是差不多吧,不过,这将是正确的覆盖channelRegistered
方法,而不是channelActive
。
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
if (isGlobalLimitReached()) {
ctx.close();
} else {
ctx.pipeline().remove(this);
ctx.pipeline().addFirst(sslCtx.newHandler(ctx.alloc()));
ctx.fireChannelRegistered();
}
}
Also, you need to add SslHandler
at the beginning of pipeline on the fly and only when your condition is met (no limit reached).此外,您需要在管道的开始处动态添加SslHandler
并且仅当您的条件满足时(未达到限制)。
In that case, you'll not get SslHandshakeCompletionEvent
.在这种情况下,您将不会获得SslHandshakeCompletionEvent
。 As handshake is started when SslHandler
is added to pipeline and channel.isActive()
return true (your case in above code).当SslHandler
添加到管道并且channel.isActive()
返回 true (你在上面的代码中的情况channel.isActive()
时,握手开始。
channelRegistered
is most recent point where you can refuse/close connection. channelRegistered
是您可以拒绝/关闭连接的最新点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.