简体   繁体   English

如何在 Netty 中的 ssl 握手之前优雅地关闭通道?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM