3万字 | 34 图 | Netty | 内核角度看IO模型

作者:微信小助手

发布时间:2022-01-11T19:11:34

大家好,我是悟空呀。

今天我们从内核角度来聊下 Netty 的 IO 模型。这篇很长,建议收藏起来慢慢看~

我们都知道Netty是一个高性能异步事件驱动的网络框架。它的设计异常优雅简洁,扩展性高,稳定性强。拥有非常详细完整的用户文档。

同时内置了很多非常有用的模块基本上做到了开箱即用,用户只需要编写短短几行代码,就可以快速构建出一个具有高吞吐低延时更少的资源消耗高性能(非必要的内存拷贝最小化)等特征的高并发网络应用程序。

本文我们来探讨下支持Netty具有高吞吐低延时特征的基石----netty的网络IO模型

由Netty的网络IO模型开始,我们来正式揭开本系列Netty源码解析的序幕。

网络包接收流程

网络包收发过程.png
  • 网络数据帧通过网络传输到达网卡时,网卡会将网络数据帧通过 DMA的方式放到 环形缓冲区RingBuffer中。

RingBuffer是网卡在启动的时候分配和初始化环形缓冲队列。当RingBuffer满的时候,新来的数据包就会被丢弃。我们可以通过ifconfig命令查看网卡收发数据包的情况。其中overruns数据项表示当RingBuffer满时,被丢弃的数据包。如果发现出现丢包情况,可以通过ethtool命令来增大RingBuffer长度。

  • DMA操作完成时,网卡会向CPU发起一个 硬中断,告诉 CPU有网络数据到达。CPU调用网卡驱动注册的 硬中断响应程序。网卡硬中断响应程序会为网络数据帧创建内核数据结构 sk_buffer,并将网络数据帧 拷贝sk_buffer中。然后发起 软中断请求,通知 内核有新的网络数据帧到达。

sk_buff缓冲区,是一个维护网络帧结构的双向链表,链表中的每一个元素都是一个网络帧。虽然 TCP/IP 协议栈分了好几层,但上下不同层之间的传递,实际上只需要操作这个数据结构中的指针,而无需进行数据复制

  • 内核线程 ksoftirqd发现有软中断请求到来,随后调用网卡驱动注册的 poll函数poll函数sk_buffer中的 网络数据包送到内核协议栈中注册的 ip_rcv函数