了解网络通道缓冲区和水印

时间:2017-03-12 16:40:30

标签: java tcp buffer netty channel

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

作为一个测试案例,我有一个写入客户端的netty服务器,客户端被阻止(每次读取之间基本上有10秒的睡眠)

  • 在正常I / O下,如果接收器被阻塞,TCP发送器将受到限制(由于流控制而导致发送速度变慢),这不是这种情况。发件人似乎在每次发送时继续写入和刷新数据。这些数据写在哪里?是否会在netty的flush()中进行Flow控制? 请参阅:https://en.wikipedia.org/wiki/Transmission_Control_Protocol#Flow_control

  • 是否正在写入OS或TCP缓冲区,netty通道是否也有内部缓冲区?如果是这样,我该如何配置呢?

  • 我跟踪bytesBeforeUnwritable但它们似乎没有减少

  • 默认的高低水位是什么?我没有在我的申请中设置任何内容。有没有办法改用呢?

以下代码:

@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

  • 编译和构建:

    mvn package

  • 启动服务器

    sh scripts/Server.sh 3380

  • 启动网络代理

    sh scripts/nettyProxy.sh -l 0.0.0.0:3379 -o 127.0.0.1:3380

  • 启动客户端

    sh scripts/Client.sh 127.0.0.1 3379

  • 发送"你好"作为客户端中的标准输入

  • 一段时间后netty阻止发送,且bytesTillUnwritable不会减少。

1 个答案:

答案 0 :(得分:3)

  

这些数据写在哪里?是否会在netty的flush()中进行Flow控制?

数据转到ChannelOutboundBuffer。没有像tcp这样的Flow控件。数据将保存在ChannelOutboundBuffer中,直到tcp的发送缓冲区中有空格。

  

是否正在写入OS或TCP缓冲区,netty通道是否也有内部缓冲区?如果是这样,我该如何配置呢?

Netty有ChannelOutboundBuffer在发送到OS'buffer之前保存数据。您可以像下面这样进行配置。

    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);
  

我跟踪bytesBeforeUnwritable但它们似乎没有减少

我写了一个sample code服务器写入被阻止的客户端

您的代理AUTO_READ为假。只有在调用NettyProxyFrontendHandler#channelRead(在将来的侦听器中)时才会调用ctx.channel().read()writeAndFlush完成后将调用侦听器。 writeAndFlush将生成一个任务,当msg写入OS的缓冲区时,任务将完成。如果OS的缓冲区已满,则任务将被阻止。 netty的缓冲区不可能变得不可写,它总是可写的。

  

默认的高低水位是什么?我没有在我的申请中设置任何内容。有没有办法改用呢?

您可以在DefaultChannelConfig - >中查看defualt水印。 WriteBufferWaterMark.DEFAULT。当ChannelOutboundBuffer>中的数据时高水位标记isWritable返回false,<低水位回归真实。

 /**
 * 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();