了解 netty 通道缓冲区和水印
Understanding netty channel buffers and watermarks
我正在尝试了解 netty 缓冲区和水印。
作为测试用例,我有一个写入客户端的网络服务器,客户端被阻塞(每次读取之间基本上有 10 秒的休眠)
在正常情况下 I/O 如果接收方被阻塞,TCP 发送方将被限制(由于流量控制,发送速度变慢),这里不是这种情况。发件人似乎在每次发送时都在写入和刷新数据。这些数据写在哪里? netty 的 flush() 中是否也会有流量控制?
参见: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
启动netty代理
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
发送 "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 的发送缓冲区中有 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();
我正在尝试了解 netty 缓冲区和水印。
作为测试用例,我有一个写入客户端的网络服务器,客户端被阻塞(每次读取之间基本上有 10 秒的休眠)
在正常情况下 I/O 如果接收方被阻塞,TCP 发送方将被限制(由于流量控制,发送速度变慢),这里不是这种情况。发件人似乎在每次发送时都在写入和刷新数据。这些数据写在哪里? netty 的 flush() 中是否也会有流量控制? 参见: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
启动netty代理
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
发送 "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 的发送缓冲区中有 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();