Which Network I/O Model Should You Choose for RPC Design?
This article explains the role of network communication in RPC, compares blocking I/O, non‑blocking I/O, I/O multiplexing and asynchronous I/O, discusses why blocking I/O and multiplexing dominate, introduces zero‑copy techniques at the OS and Netty levels, and shows how Netty optimizes data handling for high‑performance RPC.
1. Common Network I/O Models
Network communication is the foundation of an RPC call: the client sends a request over the network, the server processes it and returns a response.
1.1 Blocking I/O (BIO)
In Linux, sockets are blocking by default. When a process issues a read or write system call, it is blocked until the kernel receives data, copies it to user space, and wakes the process. Each I/O operation occupies a thread for the entire duration, which can be costly under high concurrency.
1.2 I/O Multiplexing
Multiplexing (e.g., select, epoll) allows a single thread to monitor many sockets. The thread blocks on select; when any socket becomes ready, select returns and the thread reads the data. This reduces the number of threads needed for high‑concurrency workloads, though the model remains synchronous.
1.3 Why Blocking I/O and I/O Multiplexing Are Most Used
The operating system and most programming languages provide solid support for blocking I/O and multiplexing.
High‑performance network frameworks (e.g., Netty) are built on the Reactor pattern, which relies on I/O multiplexing.
For low‑concurrency scenarios, simple blocking I/O is easier to use and incurs less overhead than multiplexing.
1.4 Choosing an I/O Model for RPC Frameworks
High‑concurrency RPC services benefit from I/O multiplexing because it can handle many connections with few threads. Therefore, most RPC frameworks adopt a multiplexing‑based model (e.g., Netty with epoll on Linux).
2. Zero‑Copy
2.1 Network I/O Read/Write Process
Traditional read/write copies data between user space and kernel space twice (user→kernel, kernel→NIC for writes; NIC→kernel, kernel→user for reads), causing extra CPU cycles and context switches.
2.2 OS‑Level Zero‑Copy Techniques
Two common implementations are:
mmap + write : maps a file into memory so the kernel can transfer data directly.
sendfile : used by Nginx to transfer file data from disk to the network without copying to user space.
3. Netty Zero‑Copy
Netty also provides zero‑copy mechanisms, but they operate at the JVM level to avoid copying within user space: CompositeByteBuf merges multiple ByteBuf instances without copying. slice creates views sharing the same underlying memory. wrap wraps existing byte arrays or ByteBuffer objects as ByteBuf without copying.
Netty uses direct (off‑heap) buffers for socket I/O, achieving the same effect as OS‑level zero‑copy. Additionally, FileRegion wraps FileChannel.transferTo(), mirroring Linux sendfile.
4. Summary
Zero‑copy eliminates unnecessary CPU copies and context switches between user and kernel space, improving network throughput and overall application performance. Netty’s zero‑copy focuses on user‑space data handling, reducing internal copying and aiding in solving TCP packet fragmentation and reassembly, which is crucial for efficient RPC processing.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaEdge
First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
