了解 netty 通道缓冲区和水印

Understanding netty channel buffers and watermarks

我正在尝试了解 netty 缓冲区和水印。

作为测试用例,我有一个写入客户端的网络服务器,客户端被阻塞(每次读取之间基本上有 10 秒的休眠)

代码如下:

@Override
    public void channelRead(final ChannelHandlerContext ctx, Object msg) {

        if (server2OutboundChannel.isActive()) {
            if(server2OutboundChannel.isWritable()) {
                server2OutboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
                    @Override
                    public void operationComplete(ChannelFuture future) {
                        if (future.isSuccess()) {
                            // was able to flush out data, start to read the next chunk
                            //System.out.println(server2OutboundChannel.bytesBeforeUnwritable());
                            ctx.channel().read();
                        } else {
                            future.channel().close();
                        }
                    }
                });
            }else{
                System.out.println("Channel is no longer writeable");
                System.out.println(server2OutboundChannel.bytesBeforeUnwritable());
                System.out.println(server2OutboundChannel.bytesBeforeWritable());
            }
        }
    }

使用端到端源代码重新创建的详细步骤:

https://github.com/nipunarora/nettyDuplicator/tree/master/src/main/java/org/columbia/parikshan/proxy

Where is this data being written? Is there going to be Flow control in the netty's flush() as well?

数据去了ChannelOutboundBuffer。没有像tcp那样的流量控制。数据将保存在 ChannelOutboundBuffer 中,直到 tcp 的发送缓冲区中有 space。

Is it is being written to an OS or TCP buffer, does netty channel have an internal buffer as well? If so how can I configure it?

Netty 有 ChannelOutboundBuffer 在发送到 OS 缓冲区之前保留数据。您可以像下面这样配置它。

    Bootstrap bootstrap = new Bootstrap();
    bootstrap.option(ChannelOption.SO_RCVBUF, soRcvBufSize);
    bootstrap.option(ChannelOption.SO_SNDBUF, soSndBufSize);
    bootstrap.option(ChannelOption.WRITE_BUFFER_HIGH_WATER_MARK, writeBufferHighWaterMark);

I track bytesBeforeUnwritable but they do not seem to be decreasing

我写了一个 sample code 那个服务器写给一个阻塞的客户端

您的代理人 AUTO_READ 是错误的。 NettyProxyFrontendHandler#channelRead 只会在调用 ctx.channel().read()(未来的监听器)时调用。侦听器将在 writeAndFlush 完成后被调用。 writeAndFlush 将生成一个任务,当消息写入 OS 的缓冲区时任务将完成。如果 OS 的缓冲区已满,任务将被阻塞。 netty的buffer不可能变成不可写的,它总是可写的。

What is the default High and Low Watermark? I have not set anything in my application. Is there any way to use this instead?

您可以在DefaultChannelConfig -> WriteBufferWaterMark.DEFAULT中查看默认水位线。当数据在 ChannelOutboundBuffer > high water mark isWritable return false, < low water mark return true.

 /**
 * Returns {@code true} if and only if the I/O thread will perform the
 * requested write operation immediately.  Any write requests made when
 * this method returns {@code false} are queued until the I/O thread is
 * ready to process the queued write requests.
 */
boolean isWritable();