java - 了解 netty channel 缓冲区和水印

标签 java tcp buffer netty channel

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

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

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

  • 它正在写入操作系统或 TCP 缓冲区,netty channel 是否也有内部缓冲区?如果可以,我该如何配置?

  • 我跟踪 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 包

  • 启动服务器

    sh 脚本/Server.sh 3380

  • 启动netty代理

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

  • 启动客户端

    sh 脚本/Client.sh 127.0.0.1 3379

  • 在客户端发送“hello”作为标准输入

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

最佳答案

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

数据进入ChannelOutboundBuffer。没有像tcp那样的流量控制。数据将保存在 ChannelOutboundBuffer 中,直到 tcp 的发送缓冲区中有空间为止。

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()( future 的监听器)时调用。监听器将在 writeAndFlush 完成后被调用。 writeAndFlush 将生成一个任务,该任务将在消息写入操作系统缓冲区时完成。如果操作系统的缓冲区已满,任务将被阻塞。 netty 的缓冲区不可能变得不可写,它始终是可写的。

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 返回false,< low water mark 返回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();

关于java - 了解 netty channel 缓冲区和水印,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42750075/

相关文章:

java - 运行方法时出现很多错误

java - 使用外部电子邮件应用程序通过电子邮件发送文本输入 android

java - 为什么我们有非静态函数/方法?

java - Applet 信任库 API 代码

c# - 跟踪文件传输百分比

Vim - 当移动到具有相同缓冲区的其他窗口时调用缓冲区事件

java - opengl es 2.0 填充顶点和索引缓冲区

java - 没有最大小数位数的 NumberFormat

java - 安卓手机与PC通信: Phone can't find PC

javascript - 使用缓冲区复制 fs.createReadStream