网络系统

1. 网络协议栈

  • 即应用层数据在各层的封装格式

传输层,给应⽤数据前⾯增加了TCP头

⽹络层,给TCP数据包前⾯增加了IP头

⽹络接⼝层,给IP数据包前后分别增加了帧头和帧尾

  • 每⼀层都增加了各⾃的协议头,⽹络包的⼤⼩就增⼤
  • 网络协议栈结构

应⽤程序需要通过系统调⽤,来跟 Socket 层进⾏数据交互

Socket 层的下⾯就是传输层(TCP/UDP)、⽹络层(IP)和⽹络接⼝层(ARP)

最下⾯的⼀层,则是⽹卡驱动程序和硬件⽹卡设备

2. Linux接收网络包流程

  • 当⽹卡接收到⼀个⽹络包后,会通过 DMA 技术,将⽹络包放⼊到 Ring Buffer,这个是⼀个环形缓冲区
  • Linux 内核引⼊了 NAPI 机制来告知操作系统网络包到达,且不频繁触发中断来影响系统效率

网络包到达,网卡发起硬件中断,于是会执⾏⽹卡硬件中断处理函数

中断处理函数处理完需要「暂时屏蔽中断」

唤醒「软中断」来轮询处理数据

直到没有新数据时才恢复中断,这样⼀次中断处理多个⽹络包

  • 软中断怎么处理网络包

从 Ring Buffer 中拷⻉数据到内核缓冲区

以一个网络包交给网络协议栈逐层解析

网络接口层:检查报⽂的合法性 ,再去掉帧头帧尾,交给网络层

⽹络层:取出 IP 包,判断⽹络包下⼀步的⾛向

交给上层处理。确认给本机后,就会看是 TCP 还是 UDP,接着去掉 IP 头,然后交给传输层

转发出去

传输层取出TCP头或UDP头,根据四元组「源IP、源端⼝、⽬的IP、⽬的端⼝」作为标识,找出对应Socket,并把数据拷⻉到 Socket 的接收缓冲区

应⽤层程序调⽤ Socket 接⼝,从内核的 Socket 接收缓冲区读取新到来的数据到应⽤层

3. Linux发包流程

  • 发送⽹络包的流程正好和接收流程相反。
  • 应用层->socket缓冲区->传输层->网络层->网络接口层->软中断->网卡

4. 零拷贝

  • 什么是DMA

在进⾏ I/O 设备和内存的数据传输的时候,数据搬运的⼯作全部交给DMA 控制器,⽽ CPU 不再参与任何与数据搬运相关的事情,这样 CPU 就可以去处理别的事务

  • 什么是零拷贝

没有在内存层⾯去拷⻉数据,也就是说全程没有通过CPU 来搬运数据,所有的数据都是通过 DMA 来进⾏传输的

  • 零拷贝实现

传统IO

mmap+write

sendfile

sendfile+DMA(Linux2.4 内核版本)

  • 零拷贝项目

Kafka

Nginx

  • PageCache

在数据传输过程中,第一步都是先把数据拷贝到内核缓冲区,这个「内核缓冲区」实际上是磁盘⾼速缓存(PageCache)

PageCache 来缓存最近被访问的数据

PageCache 使⽤了「预读功能」

但是大文件传输(不能使用零拷贝)

PageCache被大文件占满,其他「热点」的⼩⽂件可能就⽆法充分使⽤到 PageCache ,降低磁盘读写性能

PageCache会很快被占满,白白浪费MDA多做的一次拷贝

  • 大文件传输:「异步 I/O + 直接 I/O」

read会阻塞很久:可以用异步IO来解决

绕过PageCache :可以只用直接IO,就是不使用PageCache

使用直接IO无法享受内核的优化

内核调度算法会尽可能缓存多次I/O请求在PageCache 中,最后「合并」成⼀个更⼤的 I/O请求再发给磁盘,减少磁盘寻址操作

无法享受预读功能

5. I/O多路复用

  • 基本的Socket模型

服务端⾸先调⽤ socket() 函数,指定网络协议、传输协议,创建scoket

调⽤bind() 函数,给这个 Socket 绑定⼀个 IP 地址和端⼝

1~2就是让发送到指定网卡和端口的数据,来到我们的应用程序

调⽤ listen() 函数进⾏监听

服务器为每个socket维护了两个队列,服务器调用accept() 函数,来从内核的全连接队列获取客户端的连接,成功返回已连接的socket;失败就阻塞

TCP 半连接队列

TCP 全连接队列

监听的 Socket 和真正⽤来传数据的 Socket 是两个:

⼀个叫作监听 Socket

⼀个叫作已连接 Socket

  • C10K问题

C 是 Client 单词⾸字⺟缩写, C10K 就是单机同时处理 1 万个请求的问题

  • Scoket如何服务多用户

理论上:对于 IPv4,客户端的 IP 数最多为 2 的 32 次⽅,客户端的端⼝数最多为 2 的 16 次⽅,也就是服务端单机最⼤ TCP 连接数约为 2 的 48 次⽅。

但是:每个socket会占用文件描述符;每个TCP连接都有数据结构,就会占用内存

最主要的是内存以及网络I/O模型

  • 多进程

为每个客户端分配⼀个进程来处理请求。

缺点:

每个进程占用系统资源,代价很重

子进程不会自动回收,会变成僵尸进程

需要手动释放

进程上下文切换,影响性能

  • 多线程

涉及到频繁创建和销毁线程

  • 线程池

消息来了放到队列,线程去取

队列是全局的,每个线程都会操作,为了避免多线程竞争,线程在操作这个队列前要加锁

C10K问题

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

后端开发面试高频八股+算法 文章被收录于专栏

涵盖各大厂考官最爱问知识点,22年最新整理!

全部评论

相关推荐

到我怀里来:教育背景不用写主修课程,还有你写班级排名是什么意思?咋不写寝室排名呢😂要写就写年纪排名。得了那么多奖结果项目经历什么技术细节都不写清楚,把技术细节写清楚,用了什么技术解决了什么问题,“用了python语言、用了SQL语言”,有这样写的?hr一看就知道你是包装的或者比赛的奖是混的,你什么技术细节都不懂。校内职务全删了,什么三好学生、文明寝室这些你写上去干嘛?重复的奖学金你写三次干嘛?自我评价写那么多干嘛?谁想看这些
点赞 评论 收藏
分享
评论
2
4
分享
牛客网
牛客企业服务