> 文档中心 > linux内核源码分析之网络协议栈的演变

linux内核源码分析之网络协议栈的演变

目录

一、C10K

1、阻塞方式

2、非阻塞1/O,多路复用模式

2.1、select与poll

2.2、epoll

3、异步I/O

二、C1000K

三、C10M


一、C10K

单机同时处理1万个请求

从资源上说,2GB内存和千兆网卡,同时处理1万个请求,只要每个请求处理占用不到200kB(2GB/10000)的内存和100Kbit(1000Mbit/10000)的网络带宽就可以。

软件上的I/O模型问题 阻塞与非阻塞

1、阻塞方式

C10k 每个请求都分配一个进程或线程,I/O很可能称为瓶颈,因为进程调度,上下文切换占用资源。

2、非阻塞1/O,多路复用模式

  • 水平触发:应用程序随时检查文件描述符的状态
  • 边沿触发,:只有在文件描述符的状态发送变化时,才发送通知

2.1、select与poll

select 和 poll 需要从文件描述符列表中,找出哪些可以执行 I/O ,然后进行读写。由于 I/O 是非阻塞的,一个线程中就可以同时监控一批套接字的文件描述符,达到了单线程处理多请求的目的。

缺点:

  • 请求数多的时候比较耗时
  • select最大文件描述符数量的限制,32位系统中,默认限制1024,时间复杂度O(N)
  • poll改进了select的表述方法,改进了一个没有固定长度的数组,没有最大描述符数量的限制,但同样进行轮询,处理耗时跟文件描述符数量的关系O(N)
  • select和poll把文件描述符的集合从用户空间 ->内核空间->用户空间 来回切换增加成本

2.2、epoll

  • epoll在linux2.6中才新增的功能
  • 使用红黑树,在内核管理文件描述符的集合,不要传入传出这个集合
  • 事件驱动机制,之关注I/O事件发生的文件描述符,不需要轮询整个集合

3、异步I/O

        异步 I/O 允许应用程序同时发起很多 I/O 操作,而不用等待这些操作完成。而在 I/O 完成后,系统会用事件通知的方式,告诉应用程序。应用程序才会去查询 I/O 操作的结果。

        异步I/O使用跟预想的逻辑不太一样,使用难度比较高,需要精心设计。

在同步和异步中取折中,可以使用协程实现。


二、C1000K

C1000K 单机支持处理100万个请求

1、物理资源:

内存:假设每个请求需要 16KB 内存的话,那么总共就需要大约 15 GB 内存。

带宽:假设只有 20% 活跃连接,即使每个连接只需要 1KB/s 的吞吐量,总共也需要 1.6 Gb/s 的吞吐量。所以还需要配置万兆网卡,或者基于多网卡 Bonding 承载更大的吞吐量。

2、软件资源:

占用大量的软件资源,比如文件描述符的数量、连接状态的跟踪、网络协议栈的缓存大小(比如套接字读写缓存、TCP 读写缓存)

大量请求带来的中断处理,也会带来非常高的处理成本。

C1000K 的解决方法,本质上还是构建在 epoll 的非阻塞 I/O 模型上,硬件和软件的优化。

 


三、C10M

C1000K 单机支持处理1000万个请求

背景:

        优化应用程序和内核中的各种网络参数,想实现 1000 万请求的并发,都是极其困难。

原因:

        Linux 内核协议栈做了太多的工作。从网卡中断带来的硬中断处理程序开始,到软中断中的各层网络协议处理,最后再到应用程序。

解决方法:

        跳过内核协议栈,把网络包直接送到要处理的应用程序那里去。常见的机制DPDK直接由用户态进程通过轮询的方式,来处理网络接收。

图片来源Introduction to DPDK: Architecture and Principles - Selectel Blog