学习网络系统的心得体会

网络系统

零拷贝

磁盘是计算机系统中读写速度最慢的的硬件之一,而零拷贝技术是用于提高文件传输性能的,通过减少上下文切换次数与数据拷贝的次数从而提高传输性能。

操作系统中IO的流程
大体流程

收到IO请求由用户态切换到内核态,CPU发送指令给磁盘控制器,磁盘控制器收到指令以后开始准备数据,数据被放入到磁盘控制器的内部缓冲区中,然后产生中断。CPU收到中断信息以后,从内部缓冲区中一个字节一个字节的读取到PageCache中,然后再从PageCache写入到用户态缓冲区中,最后再从内核态切换到用户态。

DMA技术

为了提高效率,提高CPU的使用性能,于是有了DMA技术(直接内存访问技术),数据运输工作全部交给DMA进行解决,而此时CPU就可以去做别的事情。于是流程就变成了这样:

改进以后的流程

收到IO请求由用户态切换到内核态,操作系统接收到IO请求,将请求分发给DMA,让CPU去做别的事情。DMA进一步将IO请求发送给磁盘,磁盘收到请求将数据放入到缓冲区,当缓冲区放满以后向DMA发送中断,DMA收到中断以后将缓冲区的数据读取到PageCache中,读取完毕以后再向CPU发送中断请求,最后CPU收到中断请求,将内核态的PageCache中的数据拷贝到用户态缓冲区中,再从内核态切换到用户态。

零拷贝技术

如果服务端想要对外提供文件传输的功能,那么就大体的流程就是将磁盘里面的内容读取出来然后通过网络协议发送到客户端。这期间由于传输性能太低所以就有了零拷贝技术。

没有零拷贝技术之前的流程

没有使用零拷贝需要进行四次数据拷贝以及两次上下文切换

  • 收到传输请求,从用户态切换到内核态,从磁盘中读取数据DMA拷贝到PageCache中,然后CPU再从PageCache将数据拷贝到用户态缓冲区中,再从内核态切换到用户态。
  • 再从用户态切换到内核态,将CPU用户态缓冲区中的数据拷贝到socket的缓冲区中,然后DMA再从socket的缓冲区中拷贝到网卡的缓冲区中
使用零拷贝技术之后的流程

零拷贝的实现有两种方式一种是使用mmap+write,还有一种是使用sendfile

  • mmap+write
    • 调用mmap函数以后会将磁盘缓冲区里面的数据拷贝到内核态缓冲区中,此时用户态和内核态一起共享内核态缓冲区中的磁盘数据,CPU无需再从内核态拷贝数据到用户态。用户态再调用write方法,从用户态切换到内核态以后直接将内核态缓冲区中的磁盘数据拷贝到socket中。
    • 这样的好处就是减少了一次调用CPU进行数据拷贝。
  • sendfile
    • DMA直接将磁盘缓冲区里面的数据拷贝到内核态缓冲区中,然后将缓冲区里面的描述符和数据长度传入到socket的缓冲区中,最后网卡中就可以根据socket缓冲区中的内容直接从内核态缓冲区拷贝到网卡中。
    • 这样的好处就是减少了两次拷贝过程以及两次内核态与用户态的上下文切换。
什么是PageCache

PageCache实际上就是内核缓冲区,作用有两个,一个是缓存最近被访问的数据另一个是预读功能。

  • 读取磁盘的时候优先从PageCache里面找,有就直接返回数据,没有就从磁盘中读取然后缓存到PageCache中。
  • 举个例子,假如read方法每次只能够读取100k,虽然read刚开始只会读0100k的数据,但是内核会把后面的101200k的数据都给写入到PageCache中,这样就减少了与磁盘交互的次数。
读取大文件应该怎么办

如果读取大文件的话,由于PageCache的预读功能,会把PageCache吃满导致热点小文件无法使用到PageCache的优点。为了防止这种情况的出现,应该不使用零拷贝的技术而是使用异步IO和直接IO的方式绕开PageCache,流程是:进程发起异步IO请求,然后去处理其他事情,操作系统向内核发送IO请求,磁盘将数据存储到磁盘缓冲区以后,向CPU发送中断,CPU直接将数据从磁盘缓冲区拷贝到用户态缓冲区中。

IO多路复用

网络IO的流程

在进行网络通信之前双方都需要建立一个socket,双方在读取或者传输数据的时候都通过这个socket进行数据的传输。服务端调用socket方法创建socket然后再调用bind方法给这个socket绑定ip和端口。绑定完ip和端口之后调用listen函数进行监听状态,最后通过调用accept函数从内核获取客户端连接。客户端再调用调用socket方法创建socket以后调用conect方法与服务端进行连接,接着就可以进行网络间的通信了。

TCP的最大连接数

Tcp的最大连接数限制于两个,一个是文件操作符一个是系统内存。

  • socket实际上就是一个文件,也就对应这一个文件操作符,在linux环境下文件操作符的打开数量是有限的,一般是1024。
  • 每个连接在内核中都有对饮的内存,意味着每个连接占用一定的内存。
    如果请求量很大,那么就肯定是无法满足的,为了解决这个问题就有了IO多路复用。
IO多路复用

如果为每一个请求都分配一个进程或者线程,假如说来了一万个请求就需要维护一万个进程或者线程,操作系统肯定是扛不住的。所以IO多路复用就是用一个进程来维护多个Socket,虽然说一个进程只能处理一个请求,但是如果把每个请求的时间降低,这样1秒内处理上万个请求了。

select/poll

select和poll的方式是用户态将已经连接的Socket存储在集合中,用户态将集合拷贝到内核态以后内核遍历一遍集合,查看有没有网络事件发生,有就将其进行标记。然后再将其从内核态拷贝到用户态,用户态再遍历一遍集合对标记的socket进行处理。

两者间的区别

select使用bitsmap,是一个固定长度的集合,默认的最大值为1024只能监听0~1023的文件。poll不再使用bitsmap而是使用动态的数组,突破了文件数量的限制。

epoll

epoll使用红黑树来维护待检测的socket和链表来维护就绪的socket,同时是在内核态进行维护的,减少了上下文切换的次数。红黑树用于来维护待检测的socket,当有socket就绪以后通过回调函数将其加入到链表中,用户只需要调用epoll_wait()方法就可以从链表中获取到就绪的socket而不需要遍历。

边缘触发和水平触发

边缘触发:服务端是从epoll_wait()苏醒一次,所以必须一次性读完。
水平触发:服务端会一直从epoll_wait()苏醒,直到客户端read完所有的就绪事件。

网络模式:Reactor模型和Proactor模型

Reactor模型

Reactor模型对多路IO模型的封装,由两部分组成一个是Reactor一个是处理资源池。

  • Reactor用于监听响应事件
  • 处理资源池负责处理事件
    同时分Reactor模型常见的模型又分为单Reactor单线程、单Reactor多线程、多Reactor多线程模型
单Reactor单线程

不需要考虑进程之间通信的问题,实现起来比较简单,但是没有办法充分利用多核CPU,所以处理业务逻辑的事件不能太长,否则其他连接的事务响应会有延迟。

单Reactor多线程

相比较于单Reactor单线程,多线程解决了单线程的缺陷,可以利用多核CPU,但是也带来了数据竞争的关系,但是如果并发量高的话单个Reactor承担了所有的事件监听和响应,而在在主线程运行容易成为性能瓶颈。

多Reactor多线程

相较于单Reactor,多Reactor做到了主Reactor用于监听事件,而从Reactor用于分发事件给资源处理池用于处理事件。

Proactor模型

采用异步 I/O 实现的异步网络模型,感知的是已完成的读写事件,而不需要像 Reactor 感知到事件后,还需要调用 read 来从内核中获取数据。

一致性哈希算法

现在的服务器大都是分布式部署的,一个应用部署在多台服务器上,然后通过网关将请求转发到其中的一台服务器上。为了提高系统的数据容量,会把数据水平的分到不同的节点上,比如一个分布式缓存系统,某一个key就应该到某一个节点上进行获取而不是所有的节点都能够获取。为了解决这个问题,可以使用哈希算法。比如有三台服务器,那么就将key转换成数值取模3获取到响应的服务器然后去获取数据,但是这样有个问题就是如果服务器进行扩容了,那么哈希算法也应该进行改变,数据也应该根据哈希算法的改变重新水平分发到不同的服务器上,十分麻烦。

一致性哈希

一致性哈希也是取模,只不过是对232进行取模得到一个固定值,同时将0=232使其形成一个圆。使用一致性哈希算法获取到相应的服务器分为两步,第一步:将服务器的ip进行一致性哈希处理,得到一个固定值,第二步:将获取数据的key进行一致性哈希处理,也得到一个固定值。这样两个哈希值就会被映射到一个首尾相接的圆上,然后只需要从key的位置顺时针找到第一台服务器就是存储key数据的服务器。
但是一致性哈希不是万能的,他只能减少数据迁移量,并不保证节点能够在哈希环上分布均匀,这样就会带来一个问题,会有大量的请求集中在一个节点上。假设访问请求主要集中的节点 A 上,如果节点 A 被移除了,当节点 A 宕机后,根据一致性哈希算法的规则,其上数据应该全部迁移到相邻的节点 B 上,这样,节点 B 的数据量、访问量都会迅速增加很多倍,一旦新增的压力超过了节点 B 的处理能力上限,就会导致节点 B 崩溃,进而形成雪崩式的连锁反应。

虚拟节点

为了解决节点在哈希环上分配不均的问题,可以引入虚拟节点。比如现在还是有三台服务器ABC,哈希环上只有三个节点,但是现在不再将真实节点映射到哈希环上而是将虚拟节点映射到哈希环上,然后虚拟节点再映射到真实的服务器上,这个时候就能解决哈希环上分配不均的问题,也就是负载均衡的问题。

比如对每个节点分别设置 3 个虚拟节点:对节点 A 加上编号来作为虚拟节点:A-01、A-02、A-03
对节点 B 加上编号来作为虚拟节点:B-01、B-02、B-03
对节点 C 加上编号来作为虚拟节点:C-01、C-02、C-03
引入虚拟节点后,原本哈希环上只有 3 个节点的情况,就会变成有 9 个虚拟节点映射到哈希环上,哈希环上的节点数量多了 3 倍。

参考:小林coding - 图解系统

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/49301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【vueUse库Time模块各函数简介及使用方法--全篇】

vueUse库是一个专门为Vue打造的工具库,提供了丰富的功能,包括监听页面元素的各种行为以及调用浏览器提供的各种能力等。其中的Browser模块包含了一些实用的函数,以下是这些函数的简介和使用方法: vueUse库Sensors模块各函数简介及使用方法 vueUseTime函数1. useDateFormat…

# Redis 入门到精通(七)-- redis 删除策略

Redis 入门到精通(七)-- redis 删除策略 一、redis 删除策略–过期数据的概念 1、Redis 中的数据特征 Redis 是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态。 XX :具有时效性…

Linux下git入门操作

0.创建仓库 可以按这个配置来,.gitignore中存放了上传时忽略的文件类型后缀。 1.clone仓库 在gitee上创建好仓库,点击克隆/下载, 复制地址fyehong/Linux_notes 。 在所需的文件夹中放置仓库。比如我在文件夹lesson9下存储仓库。就在less…

C# 与C++ cli

cli CLI(Command Line Interface)是一种通过命令行界面与计算机系统进行交互的方式。它提供了一种以文本形式输入命令和接收系统输出的方法,用于执行各种操作和管理计算机系统。以下是CLI的详细解释: 一、定义与基本概念 定义&…

Linux系统下的DevOps工具链:从CI到CD

Linux系统下的DevOps工具链覆盖了从持续集成(CI)到持续部署(CD)的全过程,以下是关键环节及其常用工具: 1.版本控制 (SCM) •Git: 管理代码版本,分支合并,是DevOps流程的基础。 2.…

Android中Intent和IntentFilter

目录 一 概述二 使用2.1 显式调用2.2 隐式调用2.3 IntentFilter三个属性2.3.1 action2.3.2 catagory2.3.3 data 一 概述 intent是意图,intentFilter是意图过滤器。使用intent,可以启动activity、service、broadcastReceiver等。 二 使用 2.1 显式调用…

jenkins面试题全集

1. 简述什么是Jenkins ? Jenkins是一个开源的持续集成的服务器,Jenkins开源帮助我们自动构建各类项目。 Jenkins强大的插件式,使得Jenkins可以集成很多软件,可以帮助我们持续集成我们的工程项目,对于我们测试来说&…

机车 - 凯旋(Triumph)Street Triple 765系列的R版和RS版的区别

凯旋(Triumph)Street Triple 765系列的R版和RS版有一些显著的差异,主要体现在性能、配置和价格方面。选择哪一个版本取决于你的骑行需求、预算和骑行经验。以下是两者的主要区别和一些建议: 差异点 1. 性能: * 发动机…

AI学习指南机器学习篇-t-SNE的优缺点

AI学习指南机器学习篇-t-SNE的优缺点 在机器学习领域,t-SNE(t-Distributed Stochastic Neighbor Embedding)是一种非常强大且流行的降维算法。它被广泛应用于数据可视化、特征提取等任务中。然而,与其他算法一样,t-SN…

Python酷库之旅-第三方库Pandas(041)

目录 一、用法精讲 136、pandas.Series.ne方法 136-1、语法 136-2、参数 136-3、功能 136-4、返回值 136-5、说明 136-6、用法 136-6-1、数据准备 136-6-2、代码示例 136-6-3、结果输出 137、pandas.Series.eq方法 137-1、语法 137-2、参数 137-3、功能 137-4、…

医疗信息化之PACS系统源码,C#医学影像系统源码,成熟在用稳定运中

C#语言开发的一套PACS系统源码,C/S架构,成熟稳定,多家大型综合医院应用案例。自主版权,支持二次开发,授权后可商用。 医学影像存储与传输系统是针对数据库存储、传输服务、图像处理进行了优化,存储更安全、传输更稳定、…

Ethernet/IP转CC-Link IEFB协议转化网关(通讯解决方案)

怎么样把Ethernet/IP和CC-Link IEFB网络通讯连接起来呢?最近有很多朋友咨询这个问题,在这里统一为大家详细说明一下。其实有一个设备可以很轻松地解决这个问题,名为YC-EIP-TCP,下面是详细信息。 一,设备主要功能 1、YC-EIP-CCL…

ios 15-16手机绕过ssl验证(抓取app上的https包)

绕过ssl验证的基本流程 前提概要:为什么你的charles抓不了https包 ios 越狱ios rootful安装ios 越狱商店sileo安装substitute越狱商店安装SSL Kill Switch3 全流程坑点巨多,博主亲身踩坑,务必按着步骤来 准备工作 type b to c 的数据线苹果…

【ffmpeg命令入门】实现画中画

文章目录 前言画中画是什么画中画的外观描述效果展示为什么要用画中画应用场景示例 使用FFmpeg添加画中画示例命令参数解释调整嵌入视频的位置调整嵌入视频的大小处理音频 总结 前言 FFmpeg 是一款强大的多媒体处理工具,广泛用于音视频的录制、转换和流处理。它不仅…

Vue的安全性:防范XSS攻击与安全最佳实践

引言 随着Web应用的普及,前端安全问题日益受到重视。Vue作为当下流行的前端框架,其安全性也成为开发者关注的焦点。跨站脚本攻击(XSS)是常见的Web安全漏洞之一,本文将讨论如何在使用Vue时防范XSS攻击,并分享其他Vue中的安全最佳实践。 什么是XSS攻击? XSS攻击是一种将…

Dockerfile制作部署wordpress-6.6

目录 一. 环境准备 二. 准备对应的配置文件 三. 编写Dockerfile 四. 构建镜像 五. 配置MySQL 六. 安装wordpress 七. 扩展 一. 环境准备 localhost192.168.226.25 rocky_linux9.4 Docker version 27.0.3 关闭防火墙和selinux,进行时间同步。 安装docker…

RabbitMQ普通集群搭建指南

RabbitMQ普通集群搭建指南 本文已经完全迁移至,www.geekery.cn 后续不在此更新 目标架构 本次搭建的目标是构建一个由三个节点组成的RabbitMQ集群,节点信息如下: rabbit02: IP地址 192.168.10.132rabbit03: IP地址 192.168.10.133rabbit04:…

LLM推理优化

vLLM的Paged Attention: vLLM: Easy, Fast, and Cheap LLM Serving with PagedAttention | vLLM Blog S-LoRA: S-LoRA: Serving Thousands of Concurrent LoRA Adapters (arxiv.org)

IDEA打开终端报错Cannot open Local Terminal命令行功能

idea项目中不能打开命令行功能 IDEA打开终端报错Cannot open Local Terminal 意思是打开命令行发生错误 idea上配置shell终端,命令行页面 打开右上角 File–> setting–> Tools–> 终端 找到Shell 路径 文本框中原本是是powershell.exe,现在…

SpringSecurity如何正确的设置白名单

在SpringSecurity中,往往需要对部分接口白名单访问,而大部分在使用Security中就有一个误区,那就是免鉴权访问和白名单的区别。 大部分的Security文章包括官方文档给出免鉴权访问都是使用.permitAll()去对相应路径进行免鉴权访问,但实际上这仅仅只表示该资源不需要相应的权限访问…