05、性能分析思路?

news2024/9/24 11:26:22

  1. 工具操作:包括压力工具、监控工具、剖析工具、调试工具。
  2. 数值理解:包括上面工具中所有输出的数据。
  3. 趋势分析、相关性分析、证据链分析:就是理解了工具产生的数值之后,还要把它们的逻辑关系想明白。这才是性能测试分析中最重要的一环。
  4. 最后才是调优:有了第 3 步之后,调优的方案策略就有很多种了,具体选择取决于调优成本和产生的效果。

怎么判断瓶颈

TPS曲线

        对性能瓶颈做出判断是性能分析的第一步,有了问题才能分析调优。之前有很多人在描述性能测试的过程中,说要找到性能测试中曲线上的“拐点”。我也有明确说过,大部分系统其实是没有明确的拐点的。举例来说,TPS 的视图如下:

        显然,这是一个阶梯式增加的场景,非常好。但是拐点在哪呢?有人说,显然在 1200TPS 左右的时候。也有人说了,显然是到 1500TPS 才是拐点呀。但是也有人说,这都已经能到 2000TPS 了,显然 2000TPS 是拐点。 

        我们再来看一下这张图对应的响应时间视图:

        是不是有人要说响应时间为 4.5ms 时是拐点了? 其实这些对拐点的判断,都是不合理的。如果我们对 TPS 的增加控制得更为精准的话,那么这个 TPS 的增加是有一个有清晰的弧度,而不是有一个非常清晰的拐点。

        但是至少我们可以有一个非常明确的判断,那就是瓶颈在第二个压力阶梯上已经出现了。因为响应时间增加了,TPS 增加得却没有那么多,到第三个阶梯时,显然增加的 TPS 更少了,响应时间也在不断地增加,所以,性能瓶颈在加剧,越往后就越明显。

那么我们的判断就是:

  • 有瓶颈!
  • 瓶颈和压力有关。
  • 压力呈阶梯,并且增长幅度在衰减。

如果你觉得上面的瓶颈还算清晰的话,那么我们再来看一张图:

        在这个 TPS 的曲线中,你还能判断出拐点在哪吗? 显然是判断不出来拐点的,但是我们根据图得出以下几个结论:

  • 有瓶颈!
  • 瓶颈和压力有关。
  • 压力也是阶梯的,但是并没有明确的拐点。

我们再来看一个 TPS 图:

        看到这张图,是不是明显感觉系统有瓶颈呢?那么瓶颈是不是和压力大小有关呢? 

        这种比较有规律的问题,显然不是压力大小的原因。为什么呢?因为 TPS 周期性地出现降低,并且最大的 TPS 也都恢复到了差不多的水位上。所以,即使是压力降低,也最多降低最大的 TPS 水位,会让问题出现得更晚一点,但是不会不出现。综合以上,如果画一个示意图的话,TPS 的衰减过程大概会如下所示:

  1. 随着用户数的增加,响应时间也在缓慢增加。
  2. TPS 前期一直都有增加,但是增加的幅度在变缓,直到变平。

        在这样的趋势图中,我们是看不到明确的拐点的。但是我们能做的清晰的判断就是:有瓶颈!所以对 TPS 曲线来说,它可以明确告诉我们的就是:

  1. 有没有瓶颈:其实准确说所有的系统都有性能瓶颈,只看我们在哪个量级在做性能测试了。
  2. 瓶颈和压力有没有关系:TPS 随着压力的变化而变化,那就是有关系。不管压力增不增加,TPS 都会出现曲线趋势问题,那就是无关。

        这时你可能会问,为什么不看响应时间就武断地下此结论呢?其实响应时间是用来判断业务有多快的,而 TPS 才是用来判断容量有多大的。

响应时间曲线

我们还是来看看响应时间,下面看一张响应时间图:

它对应的线程图是:

多明显的问题,随着线程的增多,响应时间也在增加,是吧。再来看它们对应的 TPS 图:

        到第 40 个线程时,TPS 基本上达到上限,为 2500 左右。响应时间随着线程数的增加而增加了,系统的瓶颈显而易见地出现了。 

        但是,如果只让你看 TPS 曲线,你是不是也会有同样的判断?那就是:有瓶颈!并且和压力有关?所以说,其实 TPS 就可以告诉我们系统有没有瓶颈了,而响应时间是用来判断业务有多快的。

怎么控制线程的递增

        讲完响应时间之后,我们再来看下线程递增。在见识了很多性能测试人员做的场景之后,必须得承认,有些场景的问题太多了。首先,我们来看两个场景的执行对比。

场景 1 的线程图:

场景 1 的 TPS 图:

 场景 1 的响应时间图:


场景 2 的线程图:

场景 2 的 TPS 图:

场景 2 的响应时间图:

 这两个场景的比对如下:

 

         有了这些对比数据之后,你是不是觉得哪里似乎是有问题的?那是对的。

        TPS 都是达到 400,但两个场景中线程递增的策略不同,产生的响应时间完全不同。虽然都没有报错,但是第一种场景是完全不符合真实的业务场景的。这是为什么呢?

        在场景的执行过程中,首先,响应时间应该是从低到高的,而在场景 1 中不是这样。其次,线程应该是递增的,而场景 1 并没有这样做(这里或许有人会想到秒杀的场景,认为场景 1 符合秒杀的业务设定,这个问题我们稍后提及)。最后,在两个场景中,TPS 的上限都达到了 400TPS。但是你可以看到,在场景 2 中,只要 40 个线程即可达到,但场景 1 中居然用到了 500 线程,显然压力过大,所以响应时间才那么长。

        其实在生产环境中,像场景 1 这样的情形是不会出现的。如果它出现了,那就是你作为性能测试的责任,因为你没有给出生产环境中应该如何控制流量的参数配置说明。

        同时,我们从上面的场景对比可以看到,对一个系统来说,如果仅在改变压力策略(其他的条件比如环境、数据、软硬件配置等都不变)的情况下,系统的最大 TPS 上限是固定的。

        场景 2 使用了递增的策略,在每个阶梯递增的过程中,出现了抖动,这就明显是系统设置的不合理导致的。设置不合理,有两种可能性:1. 资源的动态分配不合理,像后端线程池、内存、缓存等等;2. 数据没有预热。

        说到秒杀场景,有人觉得用大线程并发是合理的,其实这属于认识上的错误。因为即使线程数增加得再多,对已经达到 TPS 上限的系统来说,除了会增加响应时间之外,并无其他作用。所以我们描述系统的容量是用系统当前能处理的业务量(你用 TPS 也好,RPS 也好,HPS 也好,它们都是用来描述服务端的处理能力的),而不是压力工具中的线程数。

        那么,对于场景中线程(有些工具中叫虚拟用户)递增的策略,我们要做到以下几点:

  1. 场景中的线程递增一定是连续的,并且在递增的过程中也是有梯度的。
  2. 场景中的线程递增一定要和 TPS 的递增有比例关系,而不是突然达到最上限。后面在场景的篇幅中我们会再说它们之间的比例关系。
  3. 上面两点针对的是常规的性能场景。对于秒杀类的场景,我们前期一定是做好了系统预热的工作的,在预热之后,线程突增产生的压力,也是在可处理范围的。这时,我们可以设计线程突增的场景来看系统瞬间的处理能力。如果不能模拟出秒杀的陡增,就是不合理的场景。

        当然这里也不会是放在哪个系统中都适合的递增幅度,你还是要根据实际的测试过程来做相应的判断。 

性能衰减的过程

        有了瓶颈的判断能力,也有了线程递增的意识,那么下面在场景执行中,我们就要有判断性能衰减的能力了吧。我们先看一个压力过程中产生的结果图。

 在递增的压力过程中,随着用户数的增加。我们可以做几次计算。

  • 第一次计算,在线程达到 24 时,TPS 为 1810.6,也就是每线程每秒发出 75.44 个请求。
  • 第二次计算,在线程达到 72 时,TPS 为 4375.1,也就是每线程每秒发出 60.77 个请求。
  • 第三次计算,在线程达到 137 时,TPS 为 5034,也就是每线程每秒发出 36.74 个请求。

        通过这三次计算,我们是不是可以看到,每线程每秒发出的请求数在变少,但是整体 TPS 是在增加的。我们有很多做性能测试的人,基本上,只看 TPS 和响应时间的时候,在上面这个示例中,肯定会一直往上加用户。虽然响应时间在增加,但是增加得也不多嘛。但实际上,通过我们的计算可以知道,性能是在不断地衰减的。我们来看一张统计图:

        通过红线的大致比对可以知道,当每线程每秒的请求数降到 55 左右的时候,TPS 就达到上限了,大概在 5000 左右,再接着往上增加线程已经没有用了,响应时间开始往上增加了。

        这就是性能衰减的过程(题外话,在上图中,其实还有一个问题,就是在红线前面,性能在上升的过程中有几次抖动,这个抖动到后面变大了,也变频繁了,如果这是必然出现的抖动,那也是配置问题,希望你注意到这一点)。

        为什么要这么细致地描述性能衰减的过程呢?其实我就是想告诉你,只要每线程每秒的 TPS 开始变少,就意味着性能瓶颈已经出现了。但是瓶颈出现之后,并不是说服务器的处理能力(这里我们用 TPS 来描述)会下降,应该说 TPS 仍然会上升,在性能不断衰减的过程中,TPS 就会达到上限。

        这也是前面我说的,性能瓶颈其实在最大 TPS 之前早就已经出现了。那么我们是不是应该在性能衰减到最大 TPS 时就停止场景呢?这个不一定的哦。

        因为停不停场景,取决于我们的场景目标,如果我们只是为了得到最大 TPS,那确实可以停止场景了。但是,如果我们要扩大化性能瓶颈,也就是说为了让瓶颈更为明显,就完全不需要停止场景,只要不报错,就接着往上压,一直压到我们要说的下一个话题——响应时间变长,需要拆分。

响应时间的拆分

        在性能分析中,响应时间的拆分通常是一个分析起点。因为在性能场景中,不管是什么原因,只要系统达到了瓶颈,再接着增加压力,肯定会导致响应时间的上升,直到超时为止。

        在判断了瓶颈之后,我们需要找到问题出现在什么地方。在压力工具上看到的响应时间,都是经过了后端的每一个系统的。那么,当响应时间变长,我们就要知道,它在哪个阶段时间变长了。我们看下这张图。

        这应该是最简单的一个压力测试逻辑了。一个应用,一个 DB,结果也拆分出了 8 个时间段,这还是在我没有加上压力工具自己所消耗的时间的情况下。 

        如果我们要分析压力工具中的响应时间,拆分的逻辑就是上面这个示意图。但是在真实的场景中,基本上不是这样的。如果是内网,那基本上都是连在一个交换机上,所以通常是这样的:

        在这样的拓扑中,我们仍然可以拆出来 t1 到 t8 的时间。只是实际动手的时候,思路一定要清晰,时间拆分是从哪里到哪里,要画出来,不能混乱。

        我们有很多手段可以进行时间的拆分,当然要看我们的应用支持哪一种。如果我们是这样的架构,拆分时间应该是比较清楚的。

        首先我们需要查看 Nginx 上的时间。日志里就可以通过配置 requestt​imeupstream_response_time 得到日志如下信息: 

14.131.17.129 - - [09/Dec/2019:08:08:09 +0000] "GET / HTTP/1.1" 200 25317 0.028 0.028

         最后两列中,前面是请求时间的 28ms,后面是后端响应时间的 28ms。同时,我们再到 Tomcat 上去看时间。

172.18.0.1 - - [09/Dec/2019:08:08:09 +0000] "GET / HTTP/1.1" 200 25317 28 27 http-nio-8080-exec-1

         请求时间消耗了 28ms,响应时间消耗了 27ms。接着再来看一下前端的时间消耗。

        从这里可以看到,从发出请求到接收到第一个字节,即 TTFB 是 55.01ms,内容下载用了 11.75ms。从这就可以看得出 Nginx 基本上没消耗时间,因为它和 Tomcat 上的请求响应时间非常接近。

        那么网络上的消耗时间怎么样呢?我看到有很多人用 TTFB 来描述网络的时间。先来说明一下,TTFB 中显然包括了后端一系列处理和网络传输的时间。如下图所示。

        下面的红色点是指要接收的内容。上面的红色线就是 TTFB。 如果接收完了呢?就是这个状态。

        所以,我觉得用 TTFB 描述网络的健康状态并不合理。如果用 Content Download 来描述会更为合理。比如我们上面的这个例子中,那就是 11.75ms 下载了 25317 Bytes 的内容。

        Tomcat 上基本上是消耗了处理的所有时间,当然这中间也包括了 MySQL 花费的时间。而前端看到的其他时间就消耗在了网络中。

        在这个例子中,主要说明了响应时间怎么一步步拆。当然,如果你是下面这种情况的话,再一个个拆就比较辛苦了,需要换另一种方式。

        你肯定想知道每个系统消耗了多长时间,那么我们就需要链路监控工具来拆分时间了。比如像这样来拆分:

        从 User 开始,每个服务之间的调用时间,都需要看看时间消耗的监控。这就是时间拆分的一种方式。其实不管我们用什么样的工具来监控,最终我们想得到的无非是每个环节消耗了多长时间。用日志也好,用链路监控工具也好,甚至抓包都可以。

构建分析决策树

        分析决策树,对性能测试分析人员实在是太重要了,是性能分析中不可或缺的一环。它是对架构的梳理,是对系统的梳理,是对问题的梳理,是对查找证据链过程的梳理,是对分析思路的梳理。它起的是纵观全局,高屋建瓴的指导作用。而我要在这里跟你讲的,就是这样的方法论。

        应该说,所有的技术行业在面对自己的问题时,都需要有分析决策树。再广而推之的话,所有的问题都要有分析决策树来协助。通过上面的几个步骤,我们就会知道时间消耗在了哪个节点上。那么之后呢?又当如何?总要找到根本的原因才可以吧,我画了如下的分析决策图:

        从压力工具中,只需要知道 TPS、响应时间和错误率三条曲线,就可以明确判断瓶颈是否存在。再通过分段分层策略,结合监控平台、日志平台,或者其他的实时分析平台,知道架构中的哪个环节有问题,然后再根据更细化的架构图一一拆解下去。

        我在这里,以数据库分析和操作系统分析举一下例子。首先我们看一下数据库分析决策树。比如针对 RDBMS 中的 MySQL,我们就可以画一个如下的决策树:

         由于这里面的内容实在过多,无法一次性展现在这里。我举几个具体的例子给你说明一下。MySQL 中的索引统计信息有配置值,有状态值。我们要根据具体的结果来判断是否需要增加 key_buffer_size 值的大小。比如这种就无所谓了。

Buffer used     3.00k of   8.00M  %Used:   0.04

        从上面的数据可以看到,key buffer size 就用到了 4%,显然不用增加。再比如,我们看到这样的数据:

  __Tables_______________________
    Open             2000 of 2000    %Cache: 100.00
    Opened         15.99M     4.1/s

        这就明显有问题了。配置值为 2000 的 Open Table Cache,已经被占满了。显然这里需要分析。但是,看到状态值达到配置值并不意味着我们需要赶紧加大配置值,而是要分析是否合理,再做相应的处理。比如说上面这个,Table 确实打开得多,但是如果我们再对应看下这一条。

Slow 2 s        6.21M     1.6/s

        你是不是觉得应该先去处理慢 SQL 的问题了?关于数据库的我们就不举更多的例子了。在这里只是为了告诉你,在分析决策树的创建过程中,有非常多的相互依赖关系。然后我们再来看一下操作系统分析决策树,我在这里需要强调一下,操作系统的分析决策树,不可以绕过。

        如果你想到操作系统架构图就头大,那么这时候应该觉得有了希望。那就是我觉得操作系统上的问题判断是比较清晰的,所以基于此决策树,每个人都可以做到对操作系统中性能问题的证据链查找。但是!对嘛,总得有个但是。

        对操作系统的理解是个必然的前提。我看过很多人写的操作系统性能分析方面的书籍或资料,发现大部分人把描述计数器的数值当成性能分析。

        怎么理解这句话呢?比如说。“CPU 使用率在 TPS 上升的过程中,从 10% 增加到 95%,超过了预期值。” “内存使用率达到 99%,所以是瓶颈点。” “I/O 使用率达到 100%。” 等等。

        像这样的描述,在我的性能团队中,一定会被骂回去重写。我要这些描述有什么用?我要的是为什么达到了这样的值,原因在哪?怎么解决?就像分析决策树中所描述的那样,性能工程师要做的是一步步地细化分析,给出最终的原因。

        有人说,如果按这个路子,似乎操作系统的分析并不复杂嘛。大概三五个命令就可以跳到代码层了。是的,对于操作来说,确实不多,但是对于判断来说,那就复杂了。举个例子来说明一下:

        看到这样的图,你是不是有种手足无措的感觉?中断能占 40%,sy CPU 也能占 40%。这系统还用干业务的事吗?全干自己的事去了,可见操作系统有问题!你是不是要做这个判断了?而实际情况是,这个主机上只有一个网卡队列,而请求量又比较大。

         所以要解决的是网卡队列的问题,至于怎么解决,那手段就多了。可以换个服务器,可以多加几个队列,可以多接几个节点…

 场景的比对

        其实简单来说,就一句话:当你觉得系统中哪个环节不行的时候, 又没能力分析它,你可以直接做该环节的增加。举例来,我们现在有一个如下的架构:

 可以得到这样的结果:

        从 TPS 曲线中,我们可以明显看到系统是有瓶颈的,但是并不知道在哪里。鉴于系统架构如此简单,我们索性直接在某环节上加上一台服务器,变成这样: 

然后得到如下数据:

怎么办?再接着加其他节点,我加了更多的 JMeter 机器。

 再来看下结果:

真巧,TPS 增加了! 

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

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

相关文章

2023年第四届“华数杯”数学建模思路 - 案例:粒子群算法

# 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 什么是粒子群算法? 粒子群算法(Particle Swarm Optimization,PSO)是一种模仿鸟群、鱼群觅食行为发展起来的一种进化算…

什么是AOP

文章目录 1、AOP思想2、AOP入门案例3、AOP工作流程4、AOP切入点表达式5、AOP的五种通知类型6、AOP通知获取数据7、案例:百度网盘密码数据兼容处理8、AOP总结 1、AOP思想 AOP,即Aspect Oriented Programming,面向切面编程。是一种编程范式&am…

记一次centos 磁盘挂载过程

前言 最近买了云服务器磁盘,需要挂载,一下就由大猿来记录这次过程。 挂载过程 查看磁盘挂载情况 查看物理硬盘 lsblkfdisk -l标记分区 fdisk /dev/vdb格式化分区 xfs mkfs.xfs /dev/vdb mkfs.xfs -f /dev/vdbext4 mkfs.ext4 /dev/vdbxfs 和 ex…

[代码案例] pytorch快速上手写机器学习

任务背景 给定未来一段时间的温度,使用神经网络预测输出是天气炎热,温暖,凉爽,偏冷,寒冷 输入是未来 20天内的气温数据,输出标签是 0,1,2,3,4 代码 """Author : 琛歌很无聊Description: …

wordpress 学习贴

安装问题 我的使用环境为docker环境,php、nginx、mysql分别处于3个容器中, 提示异常,打开debug模式,会发现 No such file or directory Warning: mysqli_real_connect(): (HY000/2002): No such file or directory 这个其实问题其…

ConcurrentHashMap底层具体实现以及实现原理

问题描述 ConcurrentHashMap 底层具体实现以及实现原理 分析维度: 1. ConcurrentHashMap的整体架构 2. ConcurrentHashMap的基本功能 3. ConcurrentHashMap在性能方面的优化 解决方案: ConcurrentHashMap 的整体架构 如图所示,这个是 Concu…

int[]数组转Integer[]、List、Map「结合leetcode:第414题 第三大的数、第169题 多数元素 介绍」

文章目录 1、int[ ] 转 Integer[ ]:2、两道leetcode题遇到的场景:2.1、int[ ] 转 List<Integer> :2.2、int[ ] 转 Map: 1、int[ ] 转 Integer[ ]: public static void main(String[] args) {int[] nums {1, 2, 3}; Integer[] array Arrays.stream(nums).boxed().to…

Java反射(一)

目录 1.了解反射 2.Class类的三种实例化方法 3.反射机制与对象实例化 4.反射与单例设计模式 5.通过反射获取类结构的信息 1.了解反射 什么是反射&#xff0c;反射有什么作用 1.在Java中&#xff0c;反射是一种机制&#xff0c;允许程序在运行时动态地获取、使用和修改类的…

ASL芯片CS5261 替代瑞昱RTD2171替代AG9310芯片 Type-C转HDMI音频单转 CS5261搭配VL171母座正反插原理图性价比方案

在2021年末尾&#xff0c;瑞昱RTD2171已经停产&#xff0c;ASL集睿致远的单转Type-C转HDMI方案芯片&#xff0c;ASL集睿致远 CS5261却可以完 全替代兼容RTD2171和AG9310, CS5261芯片还可以实现对Type-C接口信号转换的同时实现投屏的慢充功能。另外如果使用芯片CS5261VL171支持T…

Nodejs 第四章(Npm install 原理)

在执行npm install 的时候发生了什么&#xff1f; 首先安装的依赖都会存放在根目录的node_modules,默认采用扁平化的方式安装&#xff0c;并且排序规则.bin第一个然后系列&#xff0c;再然后按照首字母排序abcd等&#xff0c;并且使用的算法是广度优先遍历&#xff0c;在遍历依…

【Python】Web学习笔记_flask(3)——上传文件

用GET、POST请求上传图片并呈现出来 首先还是创建文件上传的模板 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>上传图片</title> </head> <body> <form action""…

XGBoost的参数

目录 1. 迭代过程 1.1 迭代次数/学习率/初始&#x1d43b;最大迭代值 1.1.1 参数num_boost_round & 参数eta 1.1.2 参数base_score 1.1.3 参数max_delta_step 1.2 xgboost的目标函数 1.2.1 gamma对模型的影响 1.2.2 lambda对模型的影响 2. XGBoost的弱评估器 2.…

android app控制ros机器人四(调整界面布局)

半吊子改安卓&#xff0c;记录页面布局调整&#xff1a; 在ros-mobile基础上顶端增加一行&#xff0c;用于显示app名称和logo图像&#xff1b;修改标签页。 添加文字简单&#xff0c;但是替换图标长知识了&#xff0c;开始只是简单的把mipmap各个文件夹下的图片进行替换&…

Web-7-深入理解Cookie与Session:实现用户跟踪和数据存储

深入理解Cookie与Session&#xff1a;实现用户跟踪和数据存储 今日目标 1.掌握客户端会话跟踪技术Cookie 2.掌握服务端会话跟踪技术Sesssion 1.会话跟踪技术介绍 会话&#xff1a;用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断…

Spring boot开发实用篇

一、热部署 1.启动热部署 1.导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId> </dependency> 2.使用构建项目操作启动热部署 3.关于热部署 重启&#xff1a;自定义开发…

【软件测试学习】—软件测试的基本认识(一)

【软件测试学习】—软件测试的基本认识&#xff08;一&#xff09; 文章目录 【软件测试学习】—软件测试的基本认识&#xff08;一&#xff09;一、什么是软件测试二、软件测试的目的三、测试的原则四、测试的标准五、测试的基本要求六、bug的由来七、测试的流程八、开发模式九…

消息中间件应用场景介绍

提高系统性能首先考虑的是数据库的优化&#xff0c;但是数据库因为历史原因&#xff0c;横向扩展是一件非常复杂的工程&#xff0c;所有我们一般会尽量把流量都挡在数据库之前。 不管是无限的横向扩展服务器&#xff0c;还是纵向阻隔到达数据库的流量&#xff0c;都是这个思路。…

Web后端基本设计思想

JavaWeb应用的后端一般基于MVC和三层架构思想实现。 MVC是一种设计模式&#xff0c;用于开发用户界面和交互式应用程序。M即Model&#xff0c;业务模型&#xff0c;负责处理应用程序的业务逻辑和数据&#xff1b;V即View&#xff0c;视图&#xff0c;负责给用户展示界面和数据&…

【Web】web

dns与域名 网络是基于tcp/ip协议进行通信和连接的 应用层——传输层——网络层——数据链路层——物理层 每一定的台主机都有一个唯一且固定的地址标识——IP地址 IP地址的做用&#xff1a;1.区分用户和计算机&#xff1b;2.进行通信 IP地址由32位二进制数组成&#xff0c;…

<C++> 引用

1.引用的概念 引用&#xff08;Reference&#xff09;是一种别名&#xff0c;用于给变量或对象起另一个名称。引用可以理解为已经存在的变量或对象的别名&#xff0c;通过引用可以访问到原始变量或对象的内容。引用在声明时使用 & 符号来定义。 示例&#xff1a; #inclu…