Offer to come, dig friends take it! I am participating in the 2022 Spring Recruit Punch card activity. Click here for details

1. Introduction

Netty converts bytes data from the network into corresponding message data, a process called decoding in Netty. In stream-based transport, such as TCP/IP, the received data is stored in a socket receive buffer. Unfortunately, the buffer for stream-based transport is not a packet queue, but a byte queue. This means that even if you send two messages as two separate packages, the operating system does not treat them as two messages, but as a string of bytes. Therefore, there is no guarantee that what you read will be exactly the same as what your remote peer wrote. The accumulator in Netty is designed to solve this problem. We will analyze it from the following aspects

2. What is sticky bag and half bag

Sticky packets: for example, the sender should send ABC and DEF, and the receiver expects to receive ABC and DEF. But since sticky packets may receive ABCDEF

Half packet: for example, the sender should send ABCDEF, and the receiver expects to receive ABCDEF. However, because there are half packets, ABC and DEF may be received

3. How to cause sticky package or half package

Application A sends A message to application B:

  1. Application A sends the stream data to the TCP send buffer.
  2. The TCP send buffer sends data to the TCP receive buffer of server B.
  3. Application B reads the stream data from the TCP receive buffer.

Reasons for sticking package:

  • The sender writes data less than the size of the Socket buffer each time
  • The receiver does not read the Socket buffer data timely. Procedure

Reasons for half pack:

  • Data written by sender > size of Socket buffer
  • The data sent is larger than the Maximum Transmission Unit (MTU) of the protocol. Therefore, packets must be unpacked

4. How does the accumulator in the decoder solve the problem of sticky half packet

For Netty decoders, sticky packets represent bytes saved after being converted to a desired Message Message. The half-packet is bytes not decoded enough to be a Message. The current data needs to be saved to wait for new data to be decoded along with the last read. The accumulator in Netty’s decoder is to achieve this function.

    public interface Cumulator {
        /**
         * Cumulate the given {@link ByteBuf}s and return the {@link ByteBuf} that holds the cumulated bytes.
         * The implementation is responsible to correctly handle the life-cycle of the given {@link ByteBuf}s and so
         * call {@link ByteBuf#release()} if a {@link ByteBuf} is fully consumed.
         */
        ByteBuf cumulate(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf in);
    }
Copy the code

Cumulator is the internal interface of ByteToMessageDecoder.

Cumulator has two implementations in Netty:

  • MERGE_CUMULATOR (default)

    Memory replication is used. If the sum of ByteBuf is smaller than the input ByteBuf, you need to expand the sum and copy the input ByteBuf to the class Byteful.

  • COMPOSITE_CUMULATOR

    With CompositeByteBuf, bytebuF is accumulated by adding it to the CompositeByteBuf, so memory replication is avoided as much as possible

The cumulative ByteBuf is used as a variable in the decoder. This holds bytes that have not been decoded. Subsequent bytes are then merged onto the accumulated ByteBuf. Then according to unpacking specifications, such as according to fixed length. Then read bytes of a fixed length. If not, wait for the sum again.

5. To summarize

Netty cleverly uses the accumulator to save undecoded ByteBuf to the ByteBuf variable in the decoder. Subsequent incoming bytebufs are merged with those already accumulated and decoded again. And so on and so forth.

I am ant back elephant, the article is helpful to you like to pay attention to me, the article has incorrect place please give correct comments ~ thank you