At the beginning of the year, my friend attended an interview and came back to discuss this problem with me. At that time, I only knew that I did abide by this agreement in the process of ordinary use, but I really did not have a clue and did not think of the place to start.

Now, a few months later, I’d like to share my understanding of this issue with the official documentation.

The author will explain the specific reasons why Dubbo is not suitable for large text transmission from three aspects.

The I/O restrictions

This refers not only to the I/O limit that the network card writes to and emits, but also to the network bandwidth limit. Based on actual data, we calculate the performance of single link model in large text transmission.

Simulate the computing scenario

  • The server is configured with a 1000M NIC
  • Configure 50 MBIT/s network bandwidth for the client
  • A single large text occupies 512 bytes

⚠️: Carriers and nic manufacturers usually use M bits rather than M bytes

The data after integrating the units should be:

  • 1000M Bit ≈ 128 M Byte
  • 50 M Bit ≈ 7 M Byte

Maximum TPS(number of transactions per second) calculated by a single service provider: 128MB / 512K bytes = 256. Maximum TPS(transactions per second) for a single consumer to invoke a single service provider: 7MByte / 512K Byte = 14.

Assuming that the CPU capacity of the server and the client can be fully handled, then the bottleneck of the server is the nic write speed, and the bottleneck of the client is the network bandwidth. If the user can accept this TPS, then it can be considered as appropriate.

Serialization limit

The essence of Rpc frameworks such as Dubbo to perform remote calls is that the consumer transmits the execution context to the provider through network IO, and the provider can find the virtual machine internal service object through the context, and then execute the corresponding logic through reflection and finally return the result to the consumer.

The execution context in Dubbo is simply the Invocation, which provides explicit Invocation information.

/* 节选部分代码 */
public interface Invocation {

    /* Get the method name */
    String getMethodName(a);
    
    /* Get the interface name */
    String getServiceName(a);

    /* Get an array of parameter types */Class<? >[] getParameterTypes();/* Gets the call argument */
    Object[] getArguments();

}
Copy the code

The consumer translates the remote Invocation to a byte array via the serialization protocol, and the provider deserializes the byte array from the network into an object (the decode process is a lot more complicated than that, so I’ve omitted anything irrelevant here).

The actual processing is that after decoding the size of the packet, we need to wait for all bytes of the packet to arrive and then participate in serialization. At this time, all the data is in memory, and the serialized large objects also occupy memory. For our server, we do not want to see this situation.

The Channel limit

By default, Dubbo uses Netty to realize network transmission. Netty is actually based on Java NIO. In order to facilitate the receiver to unpackage the Channel, writing events are required to be queued according to the sequence.

Then in the single connection, multiple requests share a Channel to achieve data writing; When multiple requests arrive, if the packet size is too large, Channe will keep sending this packet, and the writing events of other requests will queue up, and the message cannot be sent. Of course, the response is delayed. In the worst case, a large number of requests will accumulate and time out.