简体   繁体   中英

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. Now I use Netty SslHandler with server mode to do the handshake. My current implementation is adding a ChannelInboundHandlerAdapter before the SslHandler and rewrite the channelActive method:

@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. I read the source code of Netty SslHandler . It will set handshake failure in channelInactive method when the channelInactive event is triggered. 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 .

@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).

In that case, you'll not get SslHandshakeCompletionEvent . As handshake is started when SslHandler is added to pipeline and channel.isActive() return true (your case in above code).

channelRegistered is most recent point where you can refuse/close connection.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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