4

I'm trying to figure out what happens to write requests when a channel is non-responsive. For example, this happens when the peer suddenly drops off the network, and we never get a RST.

From reading docs and Understanding netty channel buffers and watermarks, it seems that once the high WriterBufferWaterMark is reached, ChannelOutboundBuffer will be considered full, and:

Channel.isWritable() will start to return false.

From Channel.isWritable():

Returns true if and only if the I/O thread will perform the requested write operation immediately. Any write requests made when this method returns false are queued until the I/O thread is ready to process the queued write requests.

My initial question was: What happens when we keep writing anyway?

Where will the data been queued if Netty channel isWritable return false states that there is an internal buffer, and implies it is unbounded.

The question becomes, where exactly are the write requests queued, and more importantly can I observe the size of these queues?

Or: is there some limit when Netty/OS will detect that the connection is broken and needs to be closed?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
cfstras
  • 1,613
  • 15
  • 21

3 Answers3

2

Looking at the source for ChannelOutboundBuffer in 4.1.37, the method addMessage always adds incoming messages to an internal linked list, regardless of the state of isWritable. This list grows unbounded.

The total byte length of this buffer is reachable via channel.unsafe().outboundBuffer().totalPendingWriteBytes().

For an indirect value, if you don't want to use unsafe(), you can alternatively use channel.bytesBeforeWritable() which will return the queued bytes minus the low watermark.

cfstras
  • 1,613
  • 15
  • 21
1

It will still be queued in ChannelOutboundBuffer. You are responsible to stop writing once the buffer is full and start again one it empties. You can observe this via ChannelInboundHandler.channelWritabilityChanged(...).

Norman Maurer
  • 23,104
  • 2
  • 33
  • 31
  • When you say "the buffer is full", what will happen when I keep writing? Does it block? Does it fill up the LoopGroup queue? Or is there a queue of buffers? If yes, is there a way to monitor wherever the data is going? – cfstras Nov 24 '20 at 10:29
  • I've amended the question to clarify. – cfstras Nov 24 '20 at 10:35
  • If you keep on writing you may encounter OOMEs. Each write returns a future which will be notified once the write completes. Beside this there is also channelWritabilityChanged as stated before. – Norman Maurer Nov 24 '20 at 20:17
  • Thanks for the info, that got me in the right direction. – cfstras Nov 25 '20 at 12:31
0

What happens when we keep writing anyway?

When you call the ChannelHandlerContext#write method, netty will eventually write the data you want to send into a queue called channelOutboundBuffer.

When the network data receiving speed and processing speed are getting smaller and smaller due to network congestion or the high load of the Netty client, the sliding window of TCP keeps shrinking to reduce the sending of network data until it reaches zero, while the Netty server has a lot of frequent Write operation, continuously write to ChannelOutboundBuffer.

As a result, the data cannot be sent out, but the Netty server is constantly writing data, which will slowly burst the ChannelOutboundBuffer and cause OOM.

So Netty introduced LOW_WATER_MARK and HIGH_WATER_MARK to control the capacity limit of ChannelOutboundBuffer to avoid unlimited growth of ChannelOutboundBuffer

how to observe the size of these queues

you can use ctx.channel().unsafe().outboundBuffer().totalPendingWriteBytes() to Check the total memory usage of the ChannelOutboundBuffer

bin
  • 51
  • 6