我正在尝试了解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不会减少。
答案 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();