Skip to content

什么是架构师

英文 Architect 源于建筑学,在软件工程当中的架构师和建筑工程当中建筑师有很多共性,都是负责项目宏观的架构设计和整体把控;在软件工程领域中就是软件项目的总体设计师负责人

对于大部分程序员来说,架构师算是职业最终目标

互联网行业常⻅的架构师岗位

解决方案架构师:技术选型+难点攻克+沟通管理

为特定的解决方案提供一个一栈式的架构,深入理解该行业的商业模式,能够把握行业的市场和技术发展趋势,推动行业产品、解决方案和合作生态的落地

大数据架构师:技术选型+难点攻克+沟通管理

网络架构师:技术选型+难点攻克+沟通管理

应用架构师:技术选型+难点攻克+沟通管理

业务架构师:技术选型+难点攻克+沟通管理

系统架构师:技术选型+难点攻克+沟通管理

总结

虽然都是架构师【很多共性】但侧重不同, 在互联网公司里,多数架构师也充当技术 Leader 的⻆色

大公司才有很多架构师的细分,公司规模越小,架构师职责越多

架构师属于【全能型人才】

多数人的架构师成⻓方向-应用架构师

java架构师、go架构师、C++架构师 等

具体做的事情:产品PRD设计->架构师设计->方案评审->-开发->测试->上线->版本迭代更新

如何成为架构师

技术

技术解决项目业务的问题,通过业务驱动技术发展,技术反哺业务

业务起⻜是体现技术最大的价值,才能证明技术的真正价值

管理

沟通讲人话,你的业务方不指技术团队,还有产品、运营、客服团队很多

带团队、做好项目

对上汇报,对下管理

业务

识别重点+时间线

每个团队项目不少, 把握主链路

业务部⻔最需要的技术人员,口碑和技术最好的则这人的方式值得你去学习

架构师的技术广度和深度是怎样的

技术人员对技术要精还是要广,这个问题没有明确标准的答案

精于基础,广于工具,熟于业务,保持持续学习的心态

找到最适合自己的技术成⻓路径,持续学习

成⻓学习建议

学习做事方法,目标明确,推进项目落地,拿结果

沉下心来做事,最终的结果是水到渠成

不要给自己设限,学习的过程中要常去思考、总结复盘

遇到技术问题不慌乱,有自己标准的排查思路,解决后要能总结复盘

专业技能任然是立身之本,努力让自己超过同层级的技术能力,成为那20%

不要求整个架构100%掌握,掌握80%,可以理论上认为当下超过80%程序员

中台概念解释-系统复用

快速理解

不是单纯技术层面、系统层面,而是企业的组织架构,一种理念

接触过的中台概念

方法复用、类要复用、模块复用

系统复用 是更大层级上的复用,即中台

总结

中台就是以共享系统服务的形式存在,提炼各个业务域的共性需求,打造成组件化的系统

核心业务能力以服务的方式进行沉淀,实现服务在不同场景中的业务能力复用

以接口的形式提供给前台使用, 最大限度地减少系统建设中的“重复造轮子“的问题

比如:业务中台是加快系统研发上线,提高效率,但不是完全不用写任何代码,只是更少而已

分类

业务中台

业务微服务:商品中心、用户中心、支付中心、物流中心、营销中心等

技术中台

基础设施:基础服务、分布式缓存|队列|文件|调度

运维告警:监控中心、配置中心、DevOps平台

自动化平台:自动化测试平台

数据中台

数仓建设、用户画像、推荐系统、数据大屏...

AI中台

案例一(图片来源:阿里云数字政府|政府行业业务中台)

image.png

案例二:电商平台

image.png

是否要建设中台

企业IT生态系统庞大大

大量低水平重复建设的系统

各项业务数据互通

中台建设要求

要求对业务流程有一个【标准的抽象】,相关的业务能在这个标准流程里面进行

作为中台,需求肯定会很多,系统设计时要让系统可扩展性强

对系统设计抽象有比较强的品控,不要因为多人共建让系统代码迅速的腐化膨胀

突出关键能力 -【抽象能力】

顶层设计-锻炼架构师的业务抽象能力

注意

架构师的能力之一就是抽象能力

即做顶层设计,有多种方式,一种是自顶向下,另一种是自底向上

什么是抽象能力

百科解释:从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象

说人话

发现不同事物之间的共同之处,异中求同,同类归并;
抽象的层次没有确定性的答案,核心就是满足业务场景的需要
抽象层次越高,细节越少,普适性越强,把握好边界问题,适度即可

原则

越顶层越抽象

下层独立上层的存在

高内聚,低耦合

代码案例

JDK代码:java集合、IO流量的顶层类

支付平台API设计

微信支付、支付宝支付、抖音支付、京东支付

实现代码前,列举下 需要抽象的API

下单
查询订单
关闭订单
支付结果通知
申请退款
查询退款状态
退款结果通知
账单查询 下载账单

架构师必备技术一图胜千言-架构图

如何画大饼-架构图

什么是架构图

架构图 = 架构 + 图

用图的形式把系统架构展示出来,配上简单的文案

画架构图是为了什么

一图胜千言,解决沟通障碍,给不同的【业务方】看懂

业务方很多,不同人看到⻆度不一样,你让【产品经理】看 【物理部署视图】他看得懂?

画架构图有哪些理论,有没最合适的架构图画法

架构图本质上是从不同的视⻆,不同的抽象⻆度去看,业界存在多个划分理论

那画架构图肯定有一定的【架构设计理论】主流的有多个 TOGAF、RUP 4+1 等

没有最合适的的架构图画法,只有最适合的

脱离实际业务场景的架构图,基本都是不合格的

如何判断架构图的好和坏?

业务抽象设计的合理性,是否满足高内聚、低耦合的要求,不能太宽泛,也不能太细粒度

层级划分目标系统边界,自下而上 或 由上而下,一般包括 基础设施、数据层、应用层、用户层四个层次

纵向分层:上层依赖于下层越底层,越是基础服务;横向并列关系,级别相同

理清架构图类型、业务要全面、专业术语一致、图形清晰美观、颜色类型划分合理

最重要是:你的业务方能满意+看懂!!!

不同架构图应该使用哪种方法来画?

可以用的表示法和工具很多,没有太多的限制,把握对应的视图关注点才是关键

Xmind、EdrawMax、PPT、PowerDesigner
OmniGraffle、Visio、Process On

开始阶段不要陷入过度设计中,没那么多需求不一定要那么多图(你是否有那么多客户)

关于UML

没有使用标准的架构描述语言,要注明架构图元素的用意(比如方框、形状、边框、线条、颜色等等)
使用标准的架构描述语言,只要在图例里添加关键性的架构描述,但是UML不太灵活
所以可以不用UML构图,但架构图的组成元素,要保证符合一贯理解

架构理论TOGAF和初识业务架构图

遵循架构设计理论

画架构图肯定有一定的【架构设计理论】主流的有多个 TOGAF、RUP 4+1 等

什么是【 TOGAF】

全称 The Open Group Architecture Framework 企业架构标准

给企业架构专业人士之间的沟通提供一致性保障,设计上注重灵活性,可用于不同的架构⻛格。

不同架构视图承载不同的架构设计决策,支持不同的目标和用途

业务架构:定义业务战略、企业治理、组织架构和关键业务流程。

是对业务需求的提炼和抽象,使用一套方法论对项目所涉及需求的业务进行业务边界划分

能比较清晰地看到系统的业务全貌,需求分析是否做到位,功能开发是否达到预期目标,都以此为依据

比如

开发一个电商网站,理清业务逻辑,比如订单、支付、用户、商品进行划分
不用考虑技术实现、并发量、部署架构等

业务架构图中尽量不出现技术的字眼,不同架构图的读者是不同的,确保能看懂。

无技术背景人员可参与实现的讨论,向技术人员描述解决方案核心要做什么,必须实现的关键是什么

也是【老板层面】比较关注的点,常规技术同学是到 应用/数据/技术架构这层比较多

秒懂-IaaS-PaaS-SaaS

三种云服务模型, 也称为三层架构

IaaS 基础设施即服务 Infrastructure as a service

虚拟的硬件资源,如虚拟的主机、存储、网络、安全等资源
最熟悉的例子:阿里云ECS主机的带宽、磁盘空间、GPU等

PaaS 平台即服务 platform as a service

为开发人员提供了一个框架,使他们可以基于它创建自定义应用程序
最熟悉的例子:阿里云OSS、RDB、短信服务、日志服务

SaaS 软件即服务 software as a service

云应用程序服务,利用互联网向其用户提供应用程序,这些应用程序由第三方供应商管理
公司产品:淘宝、小鹅通、亚⻢逊,CRM(客户关系管理)、HRM(人力资源管理)、SCM(供应链)

它们的区别

image.png

总结

从Iaas到SaaS的过程,企业的云化的程度也越来越高,内部IT所需要做的事越来越少。

可以这么看,运维同学经常打交道的是IaaS,开发经常打交道的是PaaS,运营和客户经常打交道的是 SaaS

当个画家-教你画高大上的业务架构图

在画架构图之前,想清楚3个问题,架构图想表达什么?有什么用?给谁看?

表达是业务系统之间的关系,梳理业务结构

将复杂的业务逻辑简单化,降低理解难度,更方便业务方理解

给业务方查看,业务相关干系人

画图三步走

分层

业务按照层级进行划分,各个层级属于独立的版块
下层为上层提供服务能力支撑
比如:laaS / PaaS / SaaS

分模块

同层级中进行小归类
属于平行关系,可以独立存在
比如:能力开放平台 有运营能力平台、服务总线

分功能

独立功能划分出来,即业务入口
业务方重点关注的功能点,可以认为是微服务划分
比如
能力开放平台:有运营能力平台 里面有 服务管控、SLA承诺、计量服务

当个画家-教你画高大上的应用架构图

什么是应用架构图

是对整个系统实现的总体架构 , 应用架构和系统架构很大类似

一方面承接业务架构的落地,一方面影响技术选型

注意:一般应用架构图【不加入太多技术框架和实现】

作用

根据业务场景 对系统进分层,指出开发的原则、系统各个层次的应用服务

指导软件的研发,包括不限于制定应用规范、定义接口和数据交互协议,满足功能性需求和非功能性需求

业务方

研发人员,各层级架构师,各层级技术管理者

分类

多系统应用架构,用来分层次说明不同系统间的业务逻辑关系、系统边界等,比如分布式、微服 务

单系统应用架构,用来分层次说明系统的组成模块和功能点之间的业务逻辑关系,比如单体应用

常规分层

表示-展现层:负责用户体验

业务-服务层:负责业务逻辑

数据-访问层:负责数据库存取

案例

image.png

细分领域-技术架构图和数据架构图

image.png

什么是技术架构

应用架构本身只关心需要哪些应用系统,不关心在整个项目中你需要使用哪些技术

技术架构则是实现应用架构的承接方,识别技术需求,进行技术选型,描述技术之间的关系

解决的问题包括

技术层面的分层、开发语言、框架的选择
通信技术、存储技术的选择、非功能性需求的技术选择等

案例

image.png

什么是数据架构

描述一个组织逻辑的和物理的数据资产和数据管理资源的结构

从数据视⻆,表达数据从产生到消费应用的全过程

比如做一个电商实时大屏,数据来源有哪些,经过哪些组件处理,最终存储和应用到哪里

常规里面不加具体的技术实现,但有时会方便沟通,则加入对应的技术实现

案例

image.png

业务-应用-技术-数据架构图总结回顾

重点:业务架构是战略,应用架构是战术,技术和数据架构是装备

业务架构

表达业务是如何开展的,服务于业务目标,通过描绘业务上下层关系,简单的业务视图降低业务系统的复杂

应用架构

是对整个系统实现的总体架构,应用架构和系统架构很大类似
一方面承接业务架构的落地,一方面影响技术选型
注意:一般应用架构图【不加入太多技术框架和实现】

技术架构

应用架构本身只关心需要哪些应用系统,不关心在整个项目中你需要使用哪些技术

技术架构则是实现应用架构的承接方,识别技术需求,进行技术选型,描述技术之间的关系

解决的问题包括

技术层面的分层、开发语言、框架的选择
通信技术、存储技术的选择、非功能性需求的技术选择等

数据架构

描述一个组织逻辑的和物理的数据资产和数据管理资源的结构

从数据视⻆,表达数据从产生到消费应用的全过程

方法

架构图想表达什么?有什么用?给谁看?

画图三步走:分层、分模块、分功能

如何判断架构图的好和坏?

业务抽象设计的合理性,是否满足高内聚、低耦合的要求,不能太宽泛,也不能太细粒度

层级划分目标系统边界,自下而上 或 由上而下,一般包括 基础设施、数据层、应用层、用户层四个层次

纵向分层 上层依赖于下层越底层,越是基础服务;横向并列关系,级别相同

理清架构图类型、业务要全面、专业术语一致、图形清晰美观、颜色类型划分合理

重要是:你的业务方能满意+看懂!!!

类图

依赖关系

尖括号 + 虚线表示

当一个对象依赖另一个对象提供的服务时,就是依赖关系

继承泛化关系

三⻆ + 实线表示

泛化关系为 is-a 的关系,xx是一个yy的子类

实现关系

三⻆ + 虚线表示

开发里面的类 实现 接口

关联关系

尖括号 + 实线 表示

一个类中的 对象与对象 之间的引用关系,类中的 成员变量

组合关系

实心棱形 + 实线表示

属于强关联关系,由整体指向部分

聚合关系

空心棱形 + 实线表示

弱关联关系 ,由整体指向部分

如何上手公司项目

切记:不要直接看代码

看产品

看产品需求文档

看项目技术栈

看项目技术架构图和部署环境

看数据库ER设计和关联关系、是否有分库分表

看团队负责的功能、模块、服务、包作用

调下团队负责的某个功能链路

按照上述步骤看其他模块

如何衡量一个系统的架构设计目标

当下互联网项目面临的【核心大挑战】

业务发展需求变动快

高并发大流量

海量数据

可用性

网络+重点环境复杂

业务安全

架构目标

业务需求⻆度

高效+优质的解决当下业务需求问题

非业务需求⻆度

高性能: 请求延迟Latency再多少ms以内

高可用: SLA达到几个9

高并发: 每秒 TPS 几万

易扩展: 业务变动易调整,合理业务逻辑抽象,事件驱动架构和分布式服务

可伸缩: 快速水平伸缩,秒级扩容

安全性: 业务数据安全保证

总结

系统并非一蹴而就,架构目标也是随着变化,业务推送技术发展,技术反哺业务

系统和业务的演进,没有最好的架构,只有最适合的架构

任何一个解决方案、架构方案提出都要说下优缺点,逼迫自己思考

对业务有很好的了解,快速高效的用户的痛点

把简单的东⻄想复杂,控制好⻛险和准备好未来

把复杂的东⻄做简单,做好产品且控制好成本

最后把复杂的东⻄讲简单,做好传承

如何找问题点

先有识别问题能力,再学解决问题能力

内部因素

水管效应:最细的水管是流量瓶颈

木桶效应:最低的木桶是容量的上限,当然可以倾斜

常规四大件(哪些操作消耗四大件)

CPU:序列化、大量线程、大量计算
内存:大量对象产生/缓存使用/连接占据
带宽:大文件操作、突发流量
磁盘IO:大量文件IO、不合理日志、高频数据库操作

案例

大促前批量服务扩容,每个服务占据了数据库连接,导致底层数据库连接不够
双11修改下单地址失败,其他服务性能很好,但是这个导致了问题,从而链路奔溃

外部因素(三方服务)

支付平台

支付中心,微信支付统一下单每秒600- QPS, 多账号策略,采用负载均衡方式进行操作

云产品: CDN/存储/计算能力

节点网络覆盖度 / 产品本身的硬件资源问题
比如 视频CDN节点覆盖

互联网系统架构-三高下的架构设计

高并发

TPS

Transactions Per Second 每秒事务数,可以是一个接口、多个接口、一个业务流程, 包括增删改操作

QPS

Queries Per Second,每秒查询数,指一台服务器每秒能够响应的查询次数

QPS 只是一个简单查询的统计,不能描述增删改等操作

如果只是查询操作 TPS = QPS

高可用

SLA 衡量一个系统可用性有多高,目标系统 7 x 24 小时不间断服务,云厂商在宣传自己产品SLA时多少个9

分类

时间维度

系统可以正常使用时间与总时间之比(全年为例子)1年 = 365天 = 8760小时
99.9 = 8760 0.1% = 8760 0.001 = 8.76小时
99.99 = 8760 0.0001 = 0.876小时 = 0.87660 = 52.6分钟
99.999 = 8760 0.00001 = 0.0876小时 = 0.087660 = 5.26分钟

请求次数维度

请求总次数和失败的占比 ( 1000次请求为例子,相对简单 )
系统可用性99%: 表示1000个请求中允许1000 * (1-99%) = 10个请求出错
系统可用性99.9%: 表示1000个请求中允许1000 * (1-99.9%) = 1个请求出错。

9越多代表全年服务可用时间越⻓服务更可靠,停机时间越短

但往往存在网络/机房问题,应用更新发版导致服务不可用

大厂多数业务4个9是刚需,5个9是目标,6个9是理想

高性能

RT来衡量系统的响应速度,程序处理速度非常快延迟低Latency,所占内存少,cpu占用率低

比如系统处理一个 HTTP 请求需要 100ms,这 100ms 就是系统的响应时间

三高不是孤立的,而是相互支撑的影响的

高并发方面要求Throughput 大于 10万

高性能方面要求请求延迟Latency小于 100 ms

高可用方面要求系统可用性 SLA高于 99.99%

但随着并发量上来,请求延迟肯定增大,处理不过来则可用性就会下降

高并发+高性能技术方案

多大并发才算高并发?

需要结合具体的场景和资源投入

1万QPS的商品列表查看不属于高并发,稍微结合缓存即可
5千TPS的下单接口属于高并发,链路不一样

系统架构

无状态业务-水平扩展(Scale Out),只要增加服务器数量,就能线性扩充系统性能

架构的难点是难做到全链路的水平扩展

[负载均衡]思想

节点轮询、随机、加权轮询、节点固定hash

应用场景

网络 DNS解析轮询
网关分发请求后端服务
应用服务内部RPC负载均衡
数据存储-分库分表-负载分发

[缓存]思想

本地缓存/分布式缓存

应用场景

前端浏览器缓存静态资源
网络DNS解析缓存
应用程序 内存缓存/分布式缓存
数据存储Mysql Query Cache

[池化复用]思想

线程池/对象池/连接池/内存池

应用场景

java线程池技术
Jdbc/Redis/HttpClient连接池
SpringIOC容器对象池

[异步]思想

多线程/消息队列

应用场景

前端ajax异步请求
RocketMQ/Kafka 同步双写-异步刷盘
应用程序多线程异步处理

[预处理-惰性更新]思想

定时任务/懒加载

应用场景

运营后台报表数据,定时任务提前计算好
Mybatis懒加载

[分而治之]思想

Mater-worker

应用场景

Hadoop中的MapReduce
JDK. Fork/Join Framework
消息队列的广播消息
归并排序算法

高可用技术方案

冗余集群化 + 自动故障转移failover

集群架构

将多个相同的应用程序集中起来提供同一种服务,某个节点故障不影响系统

可以横向扩展性增加节点提高并发处理能力

实际应用

微服务集群
Redis集群/Kafka集群/Nginx集群
Nacos集群/Mysql集群/ZK集群

熔断降级

保险丝,熔断服务,为了防止整个系统故障,抛弃一些非核心的接口和数据,返回兜底数据

限流

当访问频率或者并发请求超过其承受范围的时候,考虑限流来保证接口的可用性

漏斗模型,不管流量多大均匀的流入容器,令牌桶算法,漏桶算法

隔离

服务和资源互相隔离,比如网络资源,机器资源,线程资源等,不会因为某个服务的资源不足而抢占其他服务的资源

多活架构

同城双活-双机房

两个机房部署在同城,物理距离较近,两个机房用「专线」网络连接,比单个机房内延迟要大一些,但整体的延迟是可以接受的

异地多活-两地三中心

两地是指 2 个城市,三中心是指有 3 个机房,其中 2 个机房在同一个城市

同时提供服务,第 3 个机房部署在异地,只做数据灾备

操作系统的缓存

Buffer和Cache

Buffer 是对磁盘数据的缓存, Cache 是文件数据的缓存,两者既会用在读请求,也会用在写请求,只不过是多和少区别

缓冲(buffer)是用来加速数据"写入"硬盘,保存即将要写入到磁盘上的数据

缓存(cache)是保存从磁盘上读出的数据,用来加速数据从硬盘中"读取"

Cache 和 Buffer 的是为了解决 高速设备和低速设备之间的问题而设计的中间层,通过“流量整形”提高系统性能

Cache 将低速设备中常被访问的数据缓存起来

当高速设备需要再次访问这些数据时,命中 Cache 中的数据,以减少对低速设备的访问

Buffer 用于缓冲高速设备把数据写到低速设备时带来的压力

当数据量比较大时,Buffer能将数据分割成合适的大小,分批回写到磁盘
当数据量比较小的时候,Buffer 能将分散的写操作集中进行,减少磁盘碎片和硬盘的反复寻道

磁盘和IO

为啥IO读写性能差别那么大

dd 命令实践

dd: 用指定大小的块 拷⻉一个文件,并在拷⻉的同时进行指定的转换,下面是参数

if = 文件名: 输入文件名,缺省为标准输入,即指定源文件。< if = input file >
of = 文件名: 输出文件名,缺省为标准输出,即指定目的文件。 < of = output file >
bs = bytes: 同时设置读入/输出的块大小为bytes个字节, 可代替 ibs 和 obs
count = blocks: 仅拷⻉blocks个块,块大小等于指定的字节数
bs是每次读或写的大小,即一个块的大小,count是读写块的数􏰀
shell
#操作一
# 释放所有缓存
echo 3 > /proc/sys/vm/drop_caches

dd if=/dev/zero of=xdclass_testio1 bs=1M count=1024 

#操作二
echo 3 > /proc/sys/vm/drop_caches

dd if=/dev/zero of=xdclass_testio2 bs=1M count=1024 oflag=direct 

#操作三
echo 3 > /proc/sys/vm/drop_caches

dd if=/dev/zero of=xdclass_testio3 bs=1M count=1024 oflag=sync

image.png

结果

oflag的时候,文件复制速度是 oflag=direct 的多倍
原因:默认是buffered I/O,数据写到缓存层便返回,所以速度最快
oflag=direct的速度又比 oflag=sync 快了点
原因:数据写到磁盘缓存便返回,所以速度比上面的buffered I/O方式要慢
oflag=sync 的速度最慢
原因:写入的数据全部落盘才返回,所以速度比上面的仅写到磁盘缓存要慢
物理磁盘也会带有缓存 disk cache,用于提供I/O速度, 一般磁盘中带有电容,断电也能把缓存数据刷写到磁盘中

操作系统IO和虚拟文件系统VFS

什么是操作系统IO

输入(Input)和输出(Output),或者读(Read)和写(Write)

I/O模式可以划分为本地IO模型(内存、磁盘)和网络IO模型

I/O关联到用户空间和内核空间的转换。也称为用户缓冲区和内核缓冲区

用户态的应用程序不能直接操作内核空间,需要将数据从内核空间拷⻉到用户空间才能使用

read和write操作,都只能在内核空间里执行
磁盘IO和网络IO请求都是先放在内核空间,然后加载到内存的数据

什么是文件系统

在 Linux 中一切皆文件,文件系统是管理磁盘上的全部文件,文件管理组织方式多种多样,所以文件系统存在多样化

Q: 系统把文件持久化存储在磁盘上,那很多文件怎么管理和使用呢?

这个就是文件系统的职责,实现文件数据的查询和存储
文件系统是管理数据,而存储数据的物理设备有硬盘、U 盘、SD 卡、网络存储设备等
不同的存储设备其物理结构不同,不同的物理结构就需要不同的文件系统去管理
例子
Windows有FAT12、FAT16、FAT32、NTFS、exFAT等文件系统
Linux有Ext2、Ext3、Ext4、tmpfs、NFS等文件系统

查询系统用了哪些的文件系统 df -h -T

image.png

两个核心概念

索引节点(index node)
简称inode ,记录文件的元信息,比如文件大小、访问权限、修改日期、数据存储位置等
索引节点也需要持久化存储,占用磁盘空间。
目录项(directory entry)
简称为 dentry,记录目录结构,比如文件的名字、索引节点指和其他目录项的关联关系等,树状结构居多
存储在内存中,也叫目录项缓存。

虚拟文件系统VFS(virtual File System)

Q: 操作系统上有那么多的文件系统和物理存储介质,应用程序怎么编写使用呢?

虚拟文件系统就是做这个,调用读写位于不同物理介质上的不同文件系统, 为各类文件系统提 供统一的接口进行交互
在应用程序和具体的文件系统之间引入了一个抽象层,开发者不用关心底层的存储介质和文 件系统类型就可以使用

Linux的IO存储栈简略图

平时调用 write 的时候,数据是从应用写入到了C标准库的IO Buffer(存在用户态)
在关闭流之前flush下文件,通过flush将数据主动写入到内核的Page Cache中,应用挂了,数据也安全(存在内核态)
将内核中的Page Cache中的数据写入到磁盘(缓存)中,系统挂了,数据也安全,需要调用 fsync(存在持久化介质)

总结

操作系统的多级缓存和数据的可用性
操作系统也是程序,人家程序员也要考虑高性能
高性能: 多线程异步、多级缓存
对比日常开发的java微服务项目
多线程异步操作,响应快
微服务里面的多级缓存 ,guava本地缓存和redis分布式缓存

CPU内核态和用户态切换

用户态切换和内核态切换就是上下文切换

相当于不同权限访问级别,比如:应用程序只能操作有限的权限,而操作系统可以操作更底层的权限

CPU向磁盘写数据,要先经过buffer缓冲区,然后把缓冲区的数据分批写入磁盘中

固态硬盘和标记整理回收

固态磁盘SSD

固态电子元器件组成,没有盘片、磁臂等机械部件,不需要磁道寻址,靠电容存储数据

某块区域存在数据,机械硬盘写入可以直接覆盖;而固态硬盘需要先擦出,再写入

block块 擦的越多寿命就越短,业务数据高频更新,则不太建议使用固态硬盘

最小读写单位是⻚,通常大小是 4KB、8KB

性能高,IOPS可以达到几万以上;价格比机械硬盘贵,寿命较短

组成结构

SSD 多个裸片组成
裸片 多个平面组
平面 plane(多个blcok组成)
块 block(通常64个page组成一个block)
⻚ page 4k

磁盘的擦除数据

image.png

SSD里面最小读写单位是page,但是最小擦除单位是block

一个块上的某些⻚的数据被标记删除,不能直接擦除这些的⻚,除非整个块上的⻚都被标记删除
块还有其它有效数据,当有新数据只能写入白色区域,并不能利用红色区域,时间越⻓,不能被使用的碎片越多

解决方案 GC(Garbagecollection)垃圾回收

有一套标记整理机制程序,"有效"⻚数据复制到一个"空白"块里,然后把这个块完全擦除
那些被移动出数据的块上面的⻚要么没数据,要么是标记删除的数据,直接对这个块进行擦除
擦除数据类似JVM的GC,标记整理 Mark Compact
先对对象进行一个标记,看看哪些对象是垃圾
整理会在清除的过程中,把可用的对象向前移动,让内存更为紧凑,避免内存碎片的产生
整理之后发现内存更紧凑,连续的空间更多,就不会造成内存碎片的问题

业务选择(没有绝对,公司有钱另说)

业务大量写日志系统,时间滚动会定期清除老旧的日志,日志一般读的少
大量擦出会导致SSD寿命变短,所以不适合存放在SSD硬盘上,应该用HDD硬盘

操作系统的IO技术底层机制和应用

CPU的外包小弟DMA技术

DMA (Direct Memory Access)

image.png

直接内存访问,直接内存访问是计算机科学中的一种内存访问技术

DMA之前: 要把外设的数据读入内存或把内存的数据传送到外设,一般都要通过 CPU控制完成,利用中断技术

允许某些硬件系统能够独立于 CPU 直接读写操作系统的内存,不需中央处理器(CPU)介入处理

数据传输操作在一个 DMA 控制器(DMAC)的控制下进行,在传输过程中 CPU 可以继续进行其它的工作

在大部分时间CPU和 I/O 操作都处于并行状态,系统的效率更高

应用程序的读写数据

image.png

DMA的工作总结

(读)从磁盘的缓冲区到内核缓冲区的拷⻉工作

(读)从网卡设备到内核的soket buffer的拷⻉工作

(写)从内核缓冲区到磁盘缓冲区的拷⻉工作

(写)从内核的soket buffer到网卡设备的拷⻉工作

但是: 内核缓冲区到用户缓冲区之间的拷⻉工作仍然由CPU负责

DMA技术里面的损耗

CPU的用户态和内核态切换

CPU的内存拷⻉损耗

下图应用程序从磁盘读取数据发送到网络上的损耗,程序需要两个命令。先read读取,再write写出

image.png

四次内核态和用户态的切换

四次缓冲区的拷⻉

读取: 磁盘缓冲区到内核缓冲区(DMA)
读取: 内核缓冲区到用户缓冲区(CPU)
写出: 用户缓冲区到内核缓冲区Socket Buffer(CPU)
写出: 内核缓冲区的Socket Buffer到网卡设备(DMA)

性能损耗操作

2次DMA拷⻉、2次CPU拷⻉、4次内核态用户态切换
计算机大神们怎么会容忍这类浪费呢,所以就诞生了零拷⻉

什么是零拷⻉ZeroCopy

只需要拷⻉2\3次 和 2\4的内核态和用户态的切换即可

ZeroCopy技术实现有两种(内核态和用户态切换次数不一样)

方式一 mmap + write

image.png

虚拟地址 通过多级⻚表 映射物理地址
2次DMA拷⻉、1次CPU拷⻉、4次内核态用户态切换

方式二 sendfile

Linux kernal 2.1新增发送文件的系统调用函数 sendfile( )
替代 read() 和 write() 两个系统调用,减少一次系统调用,即减少 2 次CPU上下文切换的开销
调用sendfile( ),从磁盘读取到内核缓冲区,然后直接把内核缓冲区的数据拷⻉到 socket buffer缓冲区 里
再把内核缓冲区的Socket Buffer给直接拷⻉给Socket协议栈 即网卡设备中)(DMA负责)
Sendfile( )

image.png

步骤
应用程序先调用sendfile()方法,将数据从磁盘拷⻉到内核缓冲区(DMA负责)
然后把 内核缓冲区的数据直接拷⻉到内核socket buffer(CPU负责)
然后把内核缓冲区的Socket Buffer给直接拷⻉给Socket协议栈 即网卡设备中,返回结束(DMA负 责)
损耗
2次DMA拷⻉、1次cpu拷⻉、2次内核态用户态切换
Linux 2.4+ 版本之后改进sendfile, 利用DMA Gather(带有收集功能的DMA),变成了真正的零拷⻉(没有CPU Copy)

image.png

应用程序先调用sendfile()方法,将数据从磁盘拷⻉到内核缓冲区(DMA负责)
把内存地址、偏移量的缓冲区 fd 描述符 拷⻉ 到Socket Buffer中去 拷⻉很少的数据 可忽略
  • 本质和虚拟内存的解决方法思路一样,就是内存地址的记录
然后把内核缓冲区的Socket Buffer给直接拷⻉给Socket协议栈 即网卡设备中,返回结束(DMA负责)

操作系统和计算机网络

计算机网络

OSI 七层模型、TCP/IP 四层模型和组成

网络通讯、TCP、UDP、HTTP1.0/1.1/2、HTTPS/网络安全攻防、DNS/CDN

性能优化诊断方法论

围绕两个大点

应用程序性能维度

提高吞吐量Throughput
降低延迟Latency

操作系统资源维度

CPU使用率
内存使用率
磁盘IO使用率

选择[指标]评估系统和应用程序现状

设置性能优化[目标]

进行链路基准[测试]

[分析]全链路性能瓶颈

[优化]系统和应用程序

[验证]优化后的性能指标

计算机硬件组成

1945年-科学家冯·诺依曼提了一种计算机设计实现架构,奠定现代计算机的理论基础

五大组成部分

中央处理器(Central Processing Unit,CPU)

控制器Control Unit 简称 [CU]
计算机的指挥系统,用来控制计算机其他组件的运行
运算器Arithmetic/Logic Unit 简称 [ALU]

(又名算数逻辑运算器)

运算功能,用来完成各种二进制编码做算术运算和逻辑运算,包括加减乘、与或非运算,控制器+运算器=CPU
运算器和控制器联系十分紧密,两大部件多数集成在同一芯片,统称为

存储器

内存
比如内存条 ,临时存储,断电丢失数据
外存
比如机械硬盘, 持久存储,断电不丢失数据

IO设备

输入设备input
比如键盘、鼠标、⻨克⻛、触摸屏、手写 输入板,游戏杆等
输出设备output
比如显示器、音响、打印机等

操作系统和进程

运行在计算机上最重要的一种程序,管理计算机的所有硬件和软件

用户通过系统OS来操作使用计算机硬件,属于中间层

现代操作系统核心功能

进程管理: 操作系统为进程分配任务,解决处理器的调度、分配和回收等

处理器管理: CPU的管理和分配,比如 分配进程 CPU调度执行

内存管理: 内存的管理和分配,比如给程序分配内存和释放内存

外存管理: 持久化存储的管理和分配,比如 磁盘文件写入

I/O管理: 输入/输出设备的管理,比如键盘输入和网络收发

进程

一个具有独立功能的程序对某个数据集在处理机上的执行过程,也是操作系统分配资源的基本单位

操作系统中给进程抽象了专⻔的[数据结构]

称为进程控制块,Process Control Block 简称 PCB
在操作系统代码当中是一个结构体: struct task_struct
每一个进程均有一个PCB,在创建进程时建立PCB,伴随进程运行的全过程,直到进程撤消而撤消

PCB数据结构 包含进程的多数信息

程序ID(PID、进程句柄): 一个进程都必须对应一个唯一PID,一般是整形数字
特征信息: 一般分系统进程、用户进程、或者内核进程等
进程状态: 运行、就绪、阻塞,表示进程现的运行情况
优先级: 表示获得CPU控制权的优先级大小
提供进程管理、调度所需要的信息
新建态: 进程正在被创建,操作系统为进程分配资源,初始化PCB

进程状态

就绪态: 具备运行条件,但没有空闲的CPU导致不能运行, 万事俱备,只欠一个CPU 运行态: 占有CPU,并在CPU上运行指令
阻塞态: 等待某一事件而暂时不能运行
退出态: 从系统中退出,操作系统会回收进程拥有的资源、撤销PCB

进程、线程、他们之间的关系是怎样的

进程
本质上是一个独立执行的程序,进程是操作系统进行资源分配和调度的基本概念
操作系统进行资源分配和调度的一个独立单位
线程
是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位。
一个进程中可以并发多个线程,每条线程执行不同的任务,切换受系统控制。
重点
进程拥有多个线程的时候,这些线程会共享相同的虚拟内存和全局变量资源,这些资源在上下文切换时不需要修改
同进程内的线程切换,要比多进程间的切换消耗更少的资源,所以开发中用多线程代替多进程的原因
线程上下文切换的两种情况
  • 前后两个线程属于不同进程,此时资源不共享,线程上下文切换和进程的上下文切换一样
  • 前后两个线程属于同一个进程。同进程虚拟内存共享,在切换的时候虚拟内存等资源就保持不动,只需要切换线程的私有数据,寄存器等不共享的数据
进程创建
进程一般由OS内核创建,一个进程也可以去创建另一个进程,这个去创建进程称为父进程,被创 建进程称为子进程
应用场景
  • Nginx 的master-worker进程
  • Redis 两种持久化方式
    • worker是处理真正的请求的,而master负责监控worker进程是否在正常工作
    • AOF (append only file)和 RDB (Redis DataBase)
      • 执行bgsave命令,Redis-Server会fork创建子进程,RDB持久化过程由子进程负责,会在后台异步进行快照操作,由于是子进程,所以快照生成同时还可以响应客户端请求

进程调度

Linux 是一个多任务操作系统,支持的任务同时运行的数量远远大于 CPU 的数量

进程调度 就是指【怎样安排】某一个时刻CPU运行【哪个进程】

进程调度类型

非抢占式调度 Nonpreemptive
一旦把处理机分配给某进程后,进程就会一直运行,直到该进程【完成】或【阻塞】时才会把 CPU 让给其他进程
主要用于【批处理系统】 和 某些对【实时性要求不严】的实时系统
抢占式调度 Preemptive
暂停某个正在执行的进程,将已分配给该进程的处理机重新分配给另一个进程
系统同样是把处理机分配给优先权最高的进程,在其执行期间出现了另一个其优先权更高的进程
进程调度程序就停止当前进程的执行,重新将处理机分配给新到的优先级最高的进程
主要用于比较严格的【实时系统】中
算法分类
先来先服务调度算法(FCFS,first come first served,非抢占式)
  • 按照作业/进程到达的先后顺序进行调度 ,即: 优先考虑在系统中等待时间最⻓的作业
  • 重点: 排在⻓进程后的短进程的等待时间⻓,不利于短作业/进程,⻓进程得到CPU就执行完成了,不利于短进程
  • 比如 进程一响应慢,进程二/三/四响应快,那进程一先到,其他本来很快搞定的但是没被调度到导致效率慢
短作业优先调度算法(SJF, Shortest Job First,非抢占式)
  • 预计执行时间短的进程优先分派处理机,短进程/作业(要求服务时间最短)
  • 在实际情况中占有很大比例,为了使得它们优先执行,对⻓作业不友好
  • 重点: 缩短进程的等待时间,提高系统的吞吐量
  • 比如 进程一响应慢,进程二/三/四响应快,那同等时间下,更多短进程任务完成了,吞吐量也上去了
高响应比优先调度算法(HRRN,Highest Response Ratio Next,非抢占式)
  • 在每次调度时,先计算各个作业的优先权: 优先权=响应比=(等待时间+要求服务时间)/要求服务时间
  • 因为等待时间与服务时间之和就是系统对该作业的响应时间,所以 优先权=响应比=响应时间/要求服务时间
  • 选择优先权高的进行服务需要【计算优先权信息,增加了系统的开销】是介于FCFS和SJF之间的一种折中算法
时间片轮转调度算法(RR,Round-Robin,抢占式)
  • FCFS 的方式按时间片轮流使用CPU 的调度方式,让每个进程在一定时间间隔内都可以得到响应
  • 由于高频率的进程切换,会增加了开销,且不区分任务的紧急程度
优先级调度算法(Priority Scheduling ,有抢占式和非抢占式)
  • 根据任务的紧急程度进行调度,高优先级的先处理,低优先级的慢处理
  • 通常使用【动态优先级】,如果高优先级任务很多且持续产生,那低优先级的就可能很慢才被处理
  • 分类
    • 优先级因素: 进程的等待时间、已使用的处理机时间或其他资源的使用情况
    • 非抢占式
      • 当就绪队列中出现优先级高的进程,运行完当前进程,再选择优先级高的进程。
    • 抢占式
      • 当就绪队列中出现优先级高的进程,当前进程挂起,调度优先级高的进程运行。
多级反馈队列调度算法(Multilevel Feedback Queue,抢占式)
  • 多级: 表示有多个队列,每个队列优先级从高到低,同时优先级越高时间片越短
    • 高优先级队列中已没有调度的进程,则调度次优先级队列中的进程
    • 对同个队列中的各个进程,按照时间片轮转法调度
    • 比如
      • Q1,Q2,Q3三个队列,在Q1中没有进程等待时才去调度Q2,只有Q1,Q2都为空时才会去调度 Q3
      • 队列的时间片为N,假如Q1中的作业经过N个时间片后还没有完成,则进入到Q2队列,以此类推
  • 反馈: 表示如果有新的进程加入优先级高的队列时,立刻停止当前正在运行的进程,转而去运行优先级高的队列
算法总结
一个好的调度算法考虑以下几个方面
  • 公平-保证每个进程得到合理的CPU时间
  • 高效-使CPU保持忙碌状态,总是有进程在CPU上运行
  • 响应时间-使交互用户的响应时间尽可能短
  • 周转时间: 使批处理用户等待输出的时间尽可能短
  • 吞吐量-使单位时间内处理的进程数量尽可能多
不同系统和版本支持的调度算法不一样
  • UNIX采用动态优先队列调度
  • BSD采用多级反馈队列调度
  • Windows采用抢先多任务调度

磁盘分区

计算机中存放信息的主要的存储设备就是硬盘,但是硬盘不能直接使用,必须对硬盘进行分割一块一块的硬盘区域就是磁盘分区

为啥要磁盘分区?

(可以想下 mysql数据库 为啥要分库分表)

方便管理、提升系统的效率和做好存储空间隔离分配

将系统中的程序数据按不同的使用分为几类,将不同类型的数据分别存放在不同的磁盘分区中

在每个分区上存放的都是相似的数据或程序,这样管理和维护就容易多

分区可以提升系统的效率,系统读写磁盘时,磁头移动的距离缩短了,即搜寻的范围小了

如果不运用分区,每次在硬盘上寻找信息时可能要寻找整个硬盘,所以速度会很慢

允许在一个磁盘上有多个文件系统,每个分区可以分配不同的文件系统

从而使操作系统可以识别每个分区的文件系统,从而实现文件的存储和管理

创建硬盘分区后,还不能立即使用,还需要创建文件系统,即格式化

格式化后常⻅的磁盘格式有: FAT(FAT16)、FAT32、NTFS、ext2、ext3等

硬盘分区类型

(不同类型磁盘支持分区的数量有限制)

主分区

主直接在硬盘上划分的,一个硬盘可以有1到3个主分区和1个扩展分区

拓展分区

是一个概念实际在硬盘中是看不到的,也无法直接使用扩展分区,在扩展分区中建立逻辑分区

容量

硬盘的容量=主分区的容量+扩展分区的容量

扩展分区的容量=各个逻辑分区的容量之和

零拷贝

下图应用程序从磁盘读取数据发送到网络上的损耗,程序需要两个命令 先read读取,再write写出

切换和拷贝:4 次拷贝、4 次上下文切换

mmap 函数

切换和拷贝:3 次拷贝、4 次上下文切换

sendfile 函数 优化前

切换和拷贝:3 次拷贝、2 次上下文切换

结合上述方法优化后的 sendfile 零拷贝,结合 mmap+sendfile,CPU 拷贝的时候借鉴 mmap 的思想

切换和拷贝:2 次拷贝、2 次上下文切换

零拷⻉技术和优缺点总结

零拷⻉的目标

解放CPU,避免CPU做太多事情

减少内存带宽占用

减少用户态和内核态上下文切换过多

在文件较小的时候 mmap 耗时更短,当文件较大时 sendfile 的方式最优

零拷⻉方式对比

sendfile

无法在调用过程中修改数据,只适用于应用程序不需要对所访问数据进行处理修改情况
场景
比如 静态文件传输,MQ的Broker发送消息给消费者
如果想要在传输过程中修改数据,可以使用mmap系统调用。
文件大小:适合大文件传输
切换和拷⻉: 2次上下文切换,最少 2 次数据拷⻉

mmap

在mmap调用可以在应用程序中直接修改Page Cache中的数据,使用的是mmap+write两步
调用比sendfile成本高,但优于传统I/O的拷⻉实现方式,虽然比 sendfile 多了上下文切换
但用户空间与内核空间并不需要数据拷⻉,在正确使用情况下并不比 sendfile 效率差
场景
多个线程以只读的方式同时访问一个文件, mmap 机制下多线程共享同一物理内存空间,节约内存
文件大小:适合小数据量读写
切换和拷⻉: 4 次上下文切换,3 次数据拷⻉

计算机网络

套娃一样的封装数据包,比如TCP协议是封装在IP数据包中

OSI 七层模型和TCP/IP 四层模型 两个模型哪个更好?

两个模型各有各的好,前者更详细,后者容易理解

例子

TCP/IP 四层模型 网络加密传输

HTTPS 在 HTTP 与 TCP 层之间加入了 SSL/TLS 协议

网络分层模型和主要协议

网络分层模型下,数据在各层之间的传输

类似寄快递,中转站一层层分发,省->市->县->区->村->房号->具体联系人

发送数据包

在网络协议栈中从上到下逐层处理,最终送到网卡发送出去

接收数据包

需要经过网络协议栈从下到上的逐层处理,最后送到应用程序中使用

注意

应用层是直接面向用户的一层,为应用程序提供统一协议的接口,但不是应用程序
目的是保障不同类型的应用采用的低层通信协议是一致的

TCP 三次握手详细流程

一次握手: 客户端发送一个SYN(Synchronize)数据包到服务器,用来请求建立连接,状态变为 SYN_SEND;

报文首部中的同部位SYN=1,同时随机生成初始序列号 seq=x

二次握手: 服务器收到客户端的SYN数据包,并回复一个SYN+ACK 数据包,用来确认连接,状态变为SYN_RECEIVED;

确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时随机初始化一个序列号 seq=y

三次握手: 客户端收到服务器的SYN+ACK数据包,并回复一个ACK 数据包,用来确认连接建立完成,状 态变为ESTABLISHED

确认报文的ACK=1,ack=y+1,seq=x+1

出于安全的考虑 第1次握手不能携带数据,第3次握手是可以携带数据的。

TCP为什么要三次握手而不是二次或者四次

案例一:两端同步确认序列号

案例二:防止失效的连接请求报文段被服务端接收

结论

三次握手的主要目的是保证连接是 双工+可用 的,保证双方都具有接受和发送数据的能力

防止重复历史连接的初始化 ,避免资源的浪费

同步双方初始序列号

序列号seq: 用来解决网络包乱序问题
确认号ack: 用来解决丢包的问题

记住: 可靠性传输主要是通过重传机制来保证

TCP 洪水攻击

TCP洪水攻击 基础缓解方案:TCP SYN Cookies (延缓TCB分配)

使用连接信息(源地址、源端口、目的地址、目的端口等)和一个随机数,计算出一个哈希值(SHA1)

SYN-Cookie避免内存空间被耗尽,但是加密会消耗CPU
攻击者发送大量的ACK包过来,被攻击机器将会花费大􏰁的CPU时间在计算Cookie上,造成正常的逻辑无法被执行

哈希值 被用作序列号 应答 SYN+ACK 包,客户端发送完三次握手的最后一次 ACK ,

服务器就会重新计算这个哈希值,确认是之前的 SYN+ACK 的返回包,则进入 TCP 的连接状态。

当开启了 syncookies 功能就可以在不使用 SYN 半连接队列的情况下成功建立连接,不需要维护半连接 数的限制

如果是DDOS则难解决,需要花钱购买流量设备

shell
# 开启syncookies 阿里云ECS默认开启 
# vim /etc/sysctl.conf

net.ipv4.tcp_syncookies = 1

0 值,表示关闭该功能;
1 值,表示仅当 SYN 半连接队列放不下时,再启用它; 
2 值,表示无条件开启功能

其他解决方案

增大半连接队列和全连接队列;

减少 SYN+ACK 重传次数(减小tcp_synack_retries的值)

收到syn攻击时,服务端会重传syn+ack报文到最大次数,才会断开连接,所以可以减少重传次数

遇到服务器运行异常,现象和思路总结

当发现服务器或业务卡顿的时候,通过top命令来查看服务器负载和cpu使用率,然后排查cpu占用较高 的进程

如果发现cpu使用率并不高,但是si软中断很高,且ksoftirqd进程cpu占用率高,则说明服务器持续发生 软中断

通过cat /proc/softirqs 来分析是哪类型的软中断次数最多,watch命令来查看变化最快的值(watch -d cat /proc/softirqs)

多数情况下网络发生中断的情况会比较多,通过sar命令来查看收发包速率和收发包数据量(sar -n DEV 1 -h)

验证是否是网络收发包过多导致,计算每个包的大小,判断服务器是否收到了flood攻击

通过tcpdump来抓包,分析数据包来源ip和抓包数据中的Flags来分析数据包类型 (tcpdump -i eth0 -n tcp port 80)

如果是Flood洪水攻击,可以通过调整tcp链接参数策略和防火墙封禁异常ip

如果是大规模DDOS攻击,则花钱找运营商购买流量包封堵

TCP 四次挥手详细流程

第一次

客户端发送 FIN(Finish)报文段,用于关闭客户端到服务端的数据传输,表示客户端的数据发送 完毕;

客户端进入 FIN_WAIT_1 状态

第二次

服务端收到客户端的FIN报文段后,发送ACK报文段,确认收到了客户端的FIN报文段

服务端进入CLOSE_WAIT状态,客户端接收到这个确认包后进入 FIN_WAIT_2 状态

第三次

服务端发送FIN报文段,用于关闭服务端到客户端的数据传输,表示服务端的数据发送完毕

服务器端进入 LAST_ACK 状态,等待客户端的最后一个 ACK

第四次

客户端收到服务端的FIN报文段后,发送ACK报文段,确认收到了服务端的FIN报文段

客户端接收后进入TIME_WAIT状态,在此阶段下等待2MSL时间(两个最大段生命周期,2Maximum Segment Lifetime)

如果这个时间间隔内没有收到服务端的请求,进入CLOSED状态;服务器端接收到ACK确认包之后,也进入 CLOSED 状态。

从而完成TCP四次挥手

TCP 四次挥手疑问点

Q: 为啥要等待2MSL时间?

2MSL是报文最大生存时间,是任何报文在网络上存在的最⻓时间,超过这个时间报文将被丢弃

假如最后一次客户端发送ACK给服务端没收到,超时后 服务端 重发FIN,客户端响应ACK,来回就是2个 MSL

等待2MSL,可以让本次连接持续的时间内所产生的所有报文段都从网络中消失,避免旧的报文段

RFC 793中规定一个MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟

CLOSE-WAIT 和 TIME-WAIT 的区别

CLOSE-WAIT是等待关闭

服务端收到客户端关闭连接的请求并确认之后,进入CLOSE-WAIT状态。
但服务端可能还有一些数据没有传输完成,不能立即关闭连接
所以CLOSE-WAIT状态是为了保证服务端在关闭连接之前将待发送的数据处理完

TIME-WAIT是在第四次挥手

当客户端向服务端发送ACK确认报文后进入TIME-WAIT状态,主动关闭连接的,才有time_wait状态
在HTTP请求中,如果connection头部的取值设置为close,那么多数都由服务端主动关闭连接
服务端处理完请求后主动关闭连接,所以服务端出现大􏰁time_wait状态
防止旧连接的数据包
如果客户端收到服务端的FIN报文之后立即关闭连接,但服务端对应的端口并没有关闭
客户端在相同端口建立新的连接,可能导致新连接收到旧连接的数据包,从而产生问题
保证连接正确关闭
假如客户端最后一次发送的ACK包在传输的时候丢失,由于TCP协议的超时重传机制,服务端 将重发FIN报文
如果客户端不是TIME-WAIT状态而直接关闭的话,当收到服务端重送的FIN包时,客户端会用 RST包来响应服务端
导致服务端以为有错误发生,但实际是关闭连接是没问题的

TIME-WAIT状态有啥坏处?

占用文件描述符/内存资源/CPU 和端口

为什么建立连接是三次握手,关闭连接却是四次挥手呢?

为了确保数据能够完成传输,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了 但未必所有的数据都全部发送给对方了,所以不能⻢上会关闭SOCKET

可能还需要发送一些数据给对方之后,再发送FIN报文告诉对方来表示同意现在可以关闭SOCKET连接

对比

三次握手中第二次握手SYN和ACK是一起发送
TCP断开连接的FIN 和 ACK需要分开 表示服务端仍可以接受数据,因此需要四次挥手