建设一个网站成本多少钱中英文对照网站怎么做

web/2025/10/3 4:26:47/文章来源:
建设一个网站成本多少钱,中英文对照网站怎么做,企业制作网站服务,WordPress右下角提醒引言#xff1a;性能瓶颈调优 在实际的性能测试中#xff0c;会遇到各种各样的问题#xff0c;比如 TPS 压不上去等#xff0c;导致这种现象的原因有很多#xff0c;测试人员应配合开发人员进行分析#xff0c;尽快找出瓶颈所在。 理想的性能测试指标结果可能不是很高性能瓶颈调优 在实际的性能测试中会遇到各种各样的问题比如 TPS 压不上去等导致这种现象的原因有很多测试人员应配合开发人员进行分析尽快找出瓶颈所在。 理想的性能测试指标结果可能不是很高但一定是平缓的。 性能调优步骤 确定问题根据性能监控的数据和性能分析的结果确定性能存在的问题。 确定原因确定问题之后对问题进行分析找出问题的原因。 确定解决方案改服务器参数配置/增加硬件资源配置/修改代码。 验证解决方案分析调优结果。 注意性能测试调优并不是一次完成的过程针对同一个性能问题上述步骤可能要经过多次循环才能最终完成性能调优的目标即测试发现问题 - 找原因 - 调整 - 验证 - 分析 - 再测试 ... 性能瓶颈概率分布 60%数据库瓶颈 数据库服务器 CPU 使用率高慢查询、SQL 过多、连接数过多抛出连接数过多连接池设置太小导致连接排队数据库出现死锁 25%应用瓶颈 应用出现内存泄露应用出现线程竞争/死锁程序代码的算法复杂度中间件、第三方应用出现异常计算密集型任务引起 CPU 负载高I/O 密集型任务引起 I/O 负载高 10%压测工具瓶颈 JMeter 单机负载能力有限如果需要模拟的用户请求数超过其负载极限也会导致 TPS 压不上去 5%Linux 机器出现异常 Linux 可用内存无法回收开销速率大于回收速率   系统资源 CPU 监控内容CPU 使用率、CPU 使用类型用户进程、内核进程瓶颈分析CPU已压满接近 100%需要再看其他指标的拐点所出现的时刻是否与 CPU 压满的时刻基本一致。 内存 监控内容实际内存、虚拟内存瓶颈分析内存不足时操作系统会使用虚拟内存从虚拟内存读取数据影响处理速度。 磁盘 I/O 监控内容I/O 速度、磁盘等待队列瓶颈分析磁盘 I/O 成为瓶颈时会出现磁盘I/O繁忙导致交易执行时在 I/O 处等待。 网络 监控内容网络流量带宽使用率、网络连接状态瓶颈分析如果接口传递的数据包过大超过了带宽的传输能力就会造成网络资源竞争 导致 TPS 上不去。 发现了瓶颈后只要对症下药就可以了。简单来说无论哪个地方出现瓶颈只需要降低压力或者增加这部分瓶颈资源应用软件没有瓶颈或优化空间之后即可缓解症状。 CPU 瓶颈增加 CPU 资源。内存瓶颈增加内存、释放缓存。磁盘 I/O 瓶颈更换性能更高的磁盘如固态 SSD。网络带宽瓶颈增加网络带宽。   CPU 后台服务的所有指令和数据处理都是由 CPU 负责服务对 CPU 的利用率对服务的性能起着决定性的作用。 top 参数详解 下面以 top 命令的输出例对 CPU 各项主要指标进行说明 us(user)运行未调整优先级的用户进程所消耗的 CPU 时间的百分比。 像 shell 程序、各种语言的编译器、数据库应用、web 服务器和各种桌面应用都算是运行在用户地址空间的进程。 这些程序如果不是处于 idle 状态那么绝大多数的 CPU 时间都是运行在用户态。 sy(system)运行内核进程所消耗的 CPU 时间的百分比。 所有进程要使用的系统资源都是由 Linux 内核处理的。当处于用户态用户地址空间的进程需要使用系统的资源时比如需要分配一些内存、或是执行 I/O 操作、再或者是去创建一个子进程此时就会进入内核态内核地址空间运行。事实上决定进程在下一时刻是否会被运行的进程调度程序就运行在内核态。 对于操作系统的设计来说消耗在内核态的时间应该是越少越好。通常 sy 比例过高意味着被测服务在用户态和系统态之间切换比较频繁此时系统整体性能会有一定下降。 在实践中有一类典型的情况会使 sy 变大那就是大量的 I/O 操作因此在调查 I/O 相关的问题时需要着重关注它。 大部分后台服务使用的 CPU 时间片中 us 和 sy 的占用比例是最高的。同时这两个指标又是互相影响的us 的比例高了sy 的比例就低反之亦然。 另外在使用多核 CPU 的服务器上CPU 0 负责 CPU 各核间的调度CPU 0 上的使用率过高会导致其他 CPU 核心之间的调度效率变低。因此测试过程中需要重点关注 CPU 0。 ni(niced)用做 nice 加权的进程分配的用户态 CPU 时间百分比。 每个 Linux 进程都有个优先级优先级高的进程有优先执行的权利这个叫做 pri。进程除了优先级外还有个优先级的修正值。这个修正值就叫做进程的 nice 值。这里显示的 ni 表示调整过 nice 值的进程消耗掉的 CPU 时间。如果系统中没有进程被调整过 nice 值那么 ni 就显示为 0。一般来说被测服务和服务器整体的 ni 值不会很高。如果测试过程中 ni 的值比较高需要从服务器 Linux 系统配置、被测服务运行参数查找原因。 id(idle)空闲的 CPU 时间百分比。 一般情况下 us ni id 应该接近 100%。 线上服务运行过程中需要保留一定的 id 冗余来应对突发的流量激增。 在性能测试过程中如果 id 一直很低吞吐量上不去需要检查被测服务线程/进程配置、服务器系统配置等。 wa(I/O wait)CPU 等待 I/O 完成时间百分比。 和 CPU 的处理速度相比磁盘 I/O 操作是非常慢的。有很多这样的操作比如CPU 在启动一个磁盘读写操作后需要等待磁盘读写操作的结果。在磁盘读写操作完成前CPU 只能处于空闲状态。 Linux 系统在计算系统平均负载时会把 CPU 等待 I/O 操作的时间也计算进去所以在我们看到系统平均负载过高时可以通过 wa 来判断系统的性能瓶颈是不是过多的 I/O 操作造成的。 磁盘、网络等 I/O 操作会导致 CPU 的 wa 指标提高。通常情况下网络 I/O 占用的 wa 资源不会很高而频繁的磁盘读写会导致 wa 激增。 如果被测服务不是 I/O 密集型的服务那需要检查被测服务的日志量、数据载入频率等。 如果 wa 高于 10% 则系统开始出现卡顿若高于 20% 则系统几乎动不了若高于 50% 则很可能磁盘出现故障。 hi硬中断消耗时间百分比。 si软中断消耗时间百分比。 硬中断是外设对 CPU 的中断即外围硬件发给 CPU 或者内存的异步信号就是硬中断信号软中断由软件本身发给操作系统内核的中断信号。通常是由硬中断处理程序或进程调度程序对操作系统内核的中断也就是我们常说的系统调用System Call。在性能测试过程中hi 会有一定的 CPU 占用率但不会太高。对于 I/O 密集型的服务si 的 CPU 占用率会高一些。 st虚拟机等待 CPU 资源的时间。 只有 Linux 在作为虚拟机运行时 st 才是有意义的。它表示虚机等待 CPU 资源的时间虚机分到的是虚拟 CPU当需要真实的 CPU 时可能真实的 CPU 正在运行其它虚机的任务所以需要等待。 案例分析 现象wa 与 id waIO wait的值过高表示硬盘存在 I/O 瓶颈。 ididle值高表示 CPU 较空闲。 如果 id 值高但系统响应慢时有可能是 CPU 等待分配内存此时应加大内存容量。 如果 id 值持续低于 10那么系统的 CPU 处理能力相对较低表明系统中最需要解决的资源是 CPU。 现象CPU 的 us 和 sy 不高但 wa 很高。 如果被测服务是磁盘 I/O 密集型服务wa 高属于正常现象。但如果不是此类服务最可能导致 wa 高的原因有两个 服务对磁盘读写的业务逻辑有问题读写频率过高写入数据量过大如不合理的数据载入策略、log 过多等都有可能导致这种问题。 服务器内存不足服务在 swap 分区不停的换入换出。 现象CPU 与吞吐量 CPU 占用不高吞吐量较低可能是服务端线程池启动太少。 CPU 占用很高吞吐量较低服务端处理慢可能操作数据库慢。 CPU 占用很高吞吐量很高 服务端处理能力强需要调整线程数降低 CPU 使用率。数据库连接数、慢 SQL、文件句柄优化。提升物理设备。 LOAD Linux 的系统负载指在特定时间间隔内一个 CPU 周期运行队列中的平均进程数。 注意Linux 中的 Load 体现的是整体系统负载即 CPU 负载 磁盘负载 网络负载 其余外设负载并不能完全等同于 CPU 使用率。而在其余系统如 UnixLoad 还是只代表 CPU 负载。 从服务器负载的定义可以看出服务器运行最理想的状态是所有 CPU 核心的运行队列都为 1即所有活动进程都在运行没有等待。这种状态下服务器运行在负载阈值下。 通常情况下按照经验值服务器的负载应位于阈值的 70%~80%这样既能利用服务器大部分性能又留有一定的性能冗余应对流量增长。 查看系统负载阈值的命令如下 Linux 提供了很多查看系统负载的命令最常用的是 top 和 uptime。 top 和 uptime 针对负载的输出内容相同都是系统最近 1 分钟、5 分钟、15 分钟的负载均值 这三个数值的使用方法和 CPU 核数相关首先确认 CPU 物理总核数 /proc/cpuinfo 中的 processors 的最大值不一定是 CPU 的核数有可能该 CPU 支持超线程技术从而 processors 是物理核数的 2 倍。 这里我们需要准确的核数具体方法为找到 /proc/cpuinfo 文件中所有的 physical id 后的数值取得最大的数值加一后就是实际的 CPU 个数。然后查找任意一个 processors 下的 cpu cores即是该颗 CPU 的核数实际 CPU 个数乘以核数即为 CPU 的物理总核数。 示例 [rootlocalhost home]# cat /proc/cpuinfo |grep physical id physical id : 0 physical id : 0 [rootlocalhost home]# cat /proc/cpuinfo |grep cpu cores cpu cores : 2 cpu cores : 2物理 CPU 个数为 011 个每个 CPU 的核数为 2 个所以总的物理核数为 2x12。 计算结果说明该机器的在单位时间内可以处理的进程数是 2 个如果单位时间内进程数超过 2 个就会出现拥堵的情况load 就会持续增高增高到一定程度就会出现系统崩溃等异常情况。 在性能测试过程中系统负载是评价整个系统运行状况最重要的指标之一。通常情况下 负载测试时系统负载应接近但不能超过阈值。 并发测试时系统负载最高不能超过阈值的 80%。 稳定性测试时系统负载应在阈值的 50% 左右。 机器针对突发情况的处理 如果 1 分钟 load 很高5 分钟 load 较高15 分钟 load 起伏不大的情况下说明该次高 load 为突发情况可以容忍。 如果高 load 持续导致 5 分钟和 15 分钟 load 都已经超过报警值这时候需要考虑进行处理。 如果 15 分钟 load 高于 1 分钟 load说明高 load 情况已经得到缓解。   内存 性能测试过程中对内存监控的主要目的是检查被测服务所占用内存的波动情况。 top 参数详解 在 Linux 系统中有多个命令可以获取指定进程的内存使用情况最常用的是 top 命令如下图所示 VIRT进程所使用的虚拟内存的总数。它包括所有的代码数据和共享库加上已换出的页面所有已申请的总内存空间。 RES进程正在使用的没有交换的物理内存栈、堆。申请内存后该内存段已被重新赋值。 SHR进程使用共享内存的总数。该数值只是反映可能与其它进程共享的内存不代表这段内存当前正被其他进程使用。 SWAP进程使用的虚拟内存中被换出的大小。交换的是已经申请但没有使用的空间包括栈、堆、共享内存。 DATA进程除可执行代码以外的物理内存总量即进程栈、堆申请的总空间。 从上面的解释可以看出测试过程中主要监控 RES 和 VIRT。对于使用了共享内存的多进程架构服务还需要监控 SHR。 free 参数详解 free 命令显示系统内存的使用情况包括物理内存、交换内存swap和内核缓冲区内存。如果加上 -h 选项控制显示单位输出的结果会友好很多 有时我们需要持续的观察内存的状况此时可以使用 -s 选项并指定间隔的秒数如 free -h -s 3 表示每隔 3 秒输出一次内存的使用情况直到按下 ctrl c。 Mem 行物理内存的使用情况。 Swap 行交换空间的使用情况。 swap space 是磁盘上的一块区域可以是一个分区也可以是一个文件所以具体的实现可以是 swap 分区也可以是 swap 文件。当系统物理内存吃紧时Linux 会将内存中不常访问的数据保存到 swap 上这样系统就有更多的物理内存为各个进程服务而当系统需要访问 swap 上存储的内容时再将 swap 上的数据加载到内存中这就是常说的换出和换入。 交换空间可以在一定程度上缓解内存不足的情况但是它需要读写磁盘数据所以性能不是很高。因此当交换空间内存开始使用则表明内存严重不足。 如果系统内存充足或是做性能压测的机器可以使用 swapoff -a 关闭交换空间或在 /etc/sysctl.conf 文件中设置 swappiness 值。如果系统内存不富余则需要根据物理内存的大小来设置交换空间的大小具体的策略网上有很丰富的资料。 total 列系统总的可用物理内存和交换空间大小。 used 列已经被使用的物理内存和交换空间大小。 free 列还有多少物理内存和交换空间可用使用真正尚未被使用的物理内存数量。 在吞吐量固定的前提下如果内存持续上涨那么很有可能是被测服务存在明显的内存泄漏需要使用 valgrind 等内存检查工具进行定位。 shared 列被共享使用的物理内存大小。 buffer/cache 列被 buffer 和 cache 使用了的物理内存大小。 Linux 内核为了提升磁盘操作的性能会消耗一部分空闲内存去缓存磁盘数据就是 buffer 和 cache。 如果给所有应用分配足够内存后物理内存还有剩余linux 会尽量再利用这些空闲内存以提高整体 I/O 效率其方法是把这部分剩余内存再划分为 cache 及 buffer 两部分加以利用。 所以空闲物理内存不多不一定表示系统运行状态很差因为内存的 cache 及 buffer 部分可以随时被重用在某种意义上这两部分内存也可以看作是额外的空闲内存。 available 列还可以被应用程序使用的物理内存大小。 从应用程序的角度来说available free buffer cache。请注意这只是一个很理想的计算方式实际中的数据往往有较大的误差。 释放缓存内存 方式一手动释放缓存内存 snyc echo 3 /proc/sys/vm/drop_caches free -m方式二修改 linux 配置自动释放 /proc/sys/vm/drop_caches 这个值的 0 改为 1磁盘 I/O 性能测试过程中如果被测服务对磁盘读写过于频繁会导致大量请求处于 I/O 等待的状态系统负载升高响应时间变长吞吐量下降。 性能监控时的关注点 I/O 使用率磁盘实际 I/O 是否已接近最大值接近则有问题。 I/O 队列如果当前 I/O 队列长度一直不为 0则有问题。 固态硬盘500M/s 机械硬盘不超过 200M/siostat 参数详解 Linux 下可以用 iostat 命令来监控磁盘状态。 iostat -d 2 10 表示每 2 秒统计一次基础数据统计 10 次 tps该设备每秒的传输次数。“一次传输”意思是“一次 I/O 请求”。多个逻辑请求可能会被合并为“一次 I/O 请求”。“一次传输”请求的大小是未知的。 kB_read/s每秒从设备driveexpressed读取的数据量单位为 Kilobytes。 kB_wrtn/s每秒向设备driveexpressed写入的数据量单位为 Kilobytes。 kB_read读取的总数据量单位为 Kilobytes。 kB_wrtn写入的总数量数据量单位为 Kilobytes。 从 iostat -d 的输出中能够获得系统运行最基本的统计数据。但对于性能测试来说这些数据不能提供更多的信息。需要加上 -x 参数。 iostat -x 参数详解 如 iostat -x 2 10 表示每 2 秒统计一次更详细数据统计 10 次 rrqm/s每秒这个设备相关的读取请求有多少被 Merge 了。 当系统调用需要读取数据的时候VFS 将请求发到各个 FS如果 FS 发现不同的读取请求读取的是相同 Block 的数据FS 会将这个请求合并 Merge。 wrqm/s每秒这个设备相关的写入请求有多少被 Merge 了。 await每一个 I/O 请求的处理的平均时间单位毫秒。 await 的大小一般取决于服务时间svtcm以及 I/O 队列的长度和 I/O 请求的发出模式。假设 svtcm 比较接近 await说明 I/O 差点没有等待时间。 假设 await 远大于 svctm如大于 5就要考虑 I/O 有压力瓶颈说明 I/O 队列太长应用得到的响应时间变慢。假设响应时间超过了用户能够容许的范围这时可以考虑更换更快的磁盘。 svctmI/O 平均服务时间。 %util在统计时间内有百分之多少用于 I/O 操作。 例如如果统计间隔 1 秒该设备有 0.8 秒在处理 I/O而 0.2 秒闲置那么该设备的 %util 0.8/1 80%该参数暗示了设备的繁忙程度。 %util 接近100% 表明 I/O 请求太多I/O 系统繁忙磁盘可能存在瓶颈。 iostat -x 完整参数如下- rrqm/s: 每秒进行 merge 的读操作数目。即 delta(rerge)/s - wrqm/s: 每秒进行 merge 的写操作数目。即 delta(wmerge)/s - t/s: 每秒完成的读 I/O 设备次数。即 delta(rioVs - w/s: 每秒完成的写 1/O 设备次数。即 delta(wio)/s - rsec/s: 每秒读扇区数。即 delta(rsect)/s - ws0c/s: 每秒写扇区数。即 deita(wsect)/s - rkB/s: 每秒读 K 字节数。是 rsect/s 的一半因为每扇区大小为 512 字节。需要计算 - wkB/s: 每秒写 K 字节数。是 wsect/s 的一半。需要计算 - avgrqsz: 平均每次设备 I/O 操作的数据大小扇区。delta(rsectwsect)/delta(riowio) - avgqu-sz: 平均I/O队列长度即delta(avea)/s/1000因为 aveq 的单位为毫秒。 - await: 平均每次设备 I/O 操作的等待时间毫秒。即 delta(rusewuse)/delta(riowio) - svctm: 平均每次设备 I/O 操作的服务时间毫秒。即 delta(use)/delta(riowio) - %util一秒中有百分之多少的时间用于 I/O 操作或者说一秒中有多少时间 I/O 队列是非空的。即 delta(use)/s/1000因为 use 的单位为毫秒网络 性能测试中网络监控主要包括网络流量、网络连接状态的监控。 网络流量监控 方法很多网上有很多 shell 脚本。也可以使用 nethogs 命令。该命令与 top 类似是一个实时交互的命令运行界面如下 在后台服务性能测试中对于返回文本结果的服务并不需要太多关注在流量方面。 理解带宽 针对一些特定的应用比如直播或网盘文件上传下载带宽瓶颈也是一个出现频率较高的场景。 服务端的带宽分为上行out和下行in带宽分别对应客户端的下载和上传。 看视频看新闻使用带宽客户端的下载、服务端的上行带宽。 服务端接收客户端的数据使用带宽客户端的上传、服务端的下行带宽。 一个 Web 服务器如各类新闻网站通常需要更多的服务端上行out带宽而邮件服务器、网盘服务器等则通常需要更多的服务端下行带宽in。 理解带宽速率公式 1 Mb/s 带宽速度为 128 KB/s1024Kb / 8KB 100 Mb/s 带宽速度为 12.5 Mb/s考虑网络损耗通常按 10M/s 或 1280KB/s 算 示例5000 万像素手机拍一张照片照片大小约 20MB在下述带宽下需要耗时 10M 带宽约 20 秒耗时 流量 / 速率 20MB / (10Mb/8) 20 / 1.25 16 秒按 1MB/s128KB/s 速度算即 20 秒 100M 带宽约 2 秒耗时 流量 / 速率 20MB / (100Mb/8) 20 / 12.5 1.6 秒按 10MB/s128KB/s 速度算即 2 秒 1000M 带宽约 0.2 秒耗时 流量 / 速率 20MB / (1000Mb/8) 20 / 125 0.16 秒按 100MB/s128KB/s 速度算即 0.2 秒 案例分析 现象从监控图表可以看出当前的网络流量已经基本将网络带宽占满因此网络存在瓶颈。 解决方案 硬件解决增加带宽带宽便宜。软件解决分析对应业务操作的数据传送内容是否可精简是否可以异步传送。   网络连接状态监控 性能测试中对网络的监控主要是监控网络连接状态的变化和异常。 对于使用 TCP 协议的服务需要监控服务已建立连接的变化情况即 ESTABLISHED 状态的 TCP 连接。 对于 HTTP 协议的服务需要监控被测服务对应进程的网络缓冲区的状态、TIME_WAIT 状态的连接数等。 Linux 自带的很多命令如 netstat、ss 都支持如上功能。 下图是 netstat 对指定 pid 进程的监控结果 完整命令输出 数据库 慢查询 更具体的慢 SQL 分析优化可参见《MySQL 慢 SQL 优化方案》。 如 MySQL 资源出现瓶颈首先找慢查询超过自定义的执行时间阈值的 SQL。 1通过 SQL 语句定位到慢查询日志的所在目录然后查看日志。 show variables like slow%;2慢查询日志在查询结束以后才纪录所以在应用反映执行效率出现问题时查询慢查询日志并不能定位问题。这时可以使用show processlist命令查看当前 MySQL 正在进行的线程状态可以实时地查看 SQL 的执行情况。 示例 mysql -uroot -p123456 -h127.0.0.1 -p3307 -e show full processlist |grep dbname |grep -v NULL3找到慢查询 SQL 后可以用执行计划explain进行分析或反馈给 DBA 和开发处理。推荐最简单的排查方式步骤如下 分析 SQL 是否加载了不必要的字段/数据。分析 SQL 是否命中索引。如果 SQL 很复杂优化 SQL 结构。如果表数据量太大考虑分表。…… 连接数 数据库连接池的使用率 当数据库连接池被占满时如果有新的 SQL 语句要执行只能排队等待等待连接池中的连接被释放等待之前的 SQL 语句执行完成。 如果监控发现数据库连接池的使用率过高甚至是经常出现排队的情况则需要进行调优。 查看/设置最大连接数 -- 查看最大连接数 mysql show variables like %max_connection%; ------------------------------ | Variable_name | Value | ------------------------------ | extra_max_connections | | | max_connections | 2512 | ------------------------------ 2 rows in set (0.00 sec)-- 重新设置最大连接数 set global max_connections1000;在/etc/my.cnf 里面设置数据库的最大连接数 [mysqld] max_connections 1000查看当前连接数 mysql show status like Threads%; -------------------------- | Variable_name | Value | -------------------------- | Threads_cached | 32 | | Threads_connected | 10 | | Threads_created | 50 | | Threads_rejected | 0 | | Threads_running | 1 | -------------------------- 5 rows in set (0.00 sec)Threads_connected表示当前连接数。跟 show processlist 结果相同。准确的来说Threads_running 代表的是当前并发数。 Threads_running表示激活的连接数。一般远低于 connected 数值。 Threads_created表示创建过的线程数。 如果我们在 MySQL 服务器配置文件中设置了 thread_cache_size那么当客户端断开之后服务器处理此客户的线程将会缓存起来以响应下一个客户而不是销毁前提是缓存数未达上限。 如果发现 Threads_created 值过大的话表明 MySQL 服务器一直在创建线程这也是比较耗资源因此可以适当增加配置文件中 thread_cache_size 值。 查询服务器 thread_cache_size 的值 mysql show variables like thread_cache_size; -------------------------- | Variable_name | Value | -------------------------- | thread_cache_size | 100 | -------------------------- 1 row in set (0.00 sec)## 锁 详见《MySQL 事务和锁》。   缓存命中率 通常SQL 查询是从磁盘中的数据库文件中读取数据。 若当某一个 SQL 查询语句之前执行过则该 SQL 语句及查询结果都会被缓存下来下次再查询相同的 SQL 语句时就会直接从数据库缓存中读取。注意MySQL 8 开始已废弃查询缓存功能。 监控点 业务执行过程中 SQL 查询时的缓存命中率查询语句读取缓存的次数占总查询次数的比例。 如果缓存命中率过低需要优化对应的代码和 SQL 查询语句以提高缓存命中率。   案例分析 测试结果分析 结论从目前的测试结果来看如下图所示性能存在问题。 现象并发数达到 50 时的 TPS 为 52此时虽然响应时间为 4.4s小于需求的 5s但是数据库服务器的 CPU 使用率非常高接近 100%因此需要重点关注数据库的调优分析。 排查过程 使用 top 命令观察确定是 mysqld 导致还是其他原因。 CPU 分为用户 CPU 和内核 CPU。综合其他的各项资源指标来分析发现内存、磁盘IO、网络等指标无任何异常因此判断此处不是内核 CPU 占用高主要原因是用户进程占用的 CPU 高。确认目前 CPU 占用高的为 mysqld 进程。 分析数据库服务器 CPU 高的可能原因慢 SQL、SQL 语句过多、连接数过多等。 确认是否存在慢 SQL: 查看慢查询日志看看是否有超过预期指标的 SQL 语句并分析排查看看执行计划是否准确、索引是否缺失、数据量是否太大等。目前案例经过慢查询日志的分析未存在慢查询。 确认是否 SQL 语句过多或连接数过多: 使用show full processlist查看当前数据库中正在执行的 SQL 语句及连接池的状态发现大量 SQL 在等待执行。再结合操作过程中的系统日志进行分析发现每进入一次商城首页就需要在数据库中执行 19 条查询 SQL。 解决方案 硬件解决增加 CPU。软件解决为减少一次性加载过多 SQL可考虑使用分批次、异步加载的方式展示到什么位置就查询什么位置的数据。 JAVA 应用 JVM JVMJAVA Virtual Machine虚拟出来的空间专门供 JAVA 程序运行。 JAVA 应用运行机制 JVM 体系结构介绍 JVM 内存分为三个大区young 区年轻代old 区年老代和 perm 区持久代其中 young 区又包含三个区Edgn 区、S0 区From 区、S1 区To 区。 young 区和 old 区属于 heap堆区占据堆内存perm 区称为持久代不占据堆内存。 PermSpace 主要是存放静态的类信息和方法信息、静态的方法和变量、final 标注的常量信息等。 JAVA 运行时内存划分 重点关注堆区动态变化。我们常说的性能调优指的就是堆中的性能调优。 监控点因此在测试时需要关注堆区的空间是否持续上升而没有下降。 垃圾回收机制 什么是垃圾回收机制 垃圾回收指将内存中已申请并使用完成的那部分内存空间回收供新申请使用。 垃圾回收机制都是针对堆区的内存进行的。 监控点 内存泄露一个对象持有一个引用永远不释放导致声明周期过长这样持有的对象对了内存就不够用了这样就会频繁 GC。 系统在做垃圾回收时不能够处理任何用户业务的。如果垃圾回收过于频繁导致系统业务处理能力下降。 由于 Full GC 内存比较大垃圾回收一次时间比较长那么这段时间内都不能处理业务对系统影响比较大因此我们需要关注Full GC 频率。 垃圾回收机制的运行步骤如下 新程序执行时需要先申请内存空间会先从年轻代中申请。 在年轻代满了以后就会进行垃圾回收Young GCMinor GC所有的 Minor GC 都会触发“全世界的暂停stop-the-world”停止应用程序的线程但这段时间可以忽略不计。 回收时检查年轻代中的内存是否还在使用。还在使用的部分会移存到生存区 2 中不使用的部分则释放此时年轻代内存空间被清空。 新程序执行申请内存空间再从年轻代申请。 年轻代又满了就会进行垃圾回收Young GC。还在使用的内存移存到生存区 1 中并把生存区 2 中的内存也都存到生存区 1 中。此时就会清空年轻代和生存区 2。 循环上述 1-5 步。 如果部分内存在生存区中存活很久内存在生存区中移动了 10 次左右则将这部分内存放入到老年代中。 循环上述 1-7 步直到老年代内存空间全部占满此时就要进行垃圾回收Full GCMajor GCFull Gc 会暂停所有正在执行的线程(Stop The World)来回收内存空间这个时间需要重点考虑。 JVM dump 什么是 JVM dump 在故障定位尤其是 out of memory和性能分析的时候经常会用到一些文件来帮助我们排除代码问题。这些文件记录了 JVM 运行期间的内存占用、线程执行等情况这就是我们常说的 dump 文件。 常用的有 heap dump 和 thread dump也叫 javacore或 java dump。我们可以这么理解heap dump 记录内存信息的thread dump 是记录 CPU 信息的。 当发现应用内存溢出或长时间使用内存很高的情况下通过内存 dump 进行分析可找到原因。 当发现 cpu 使用率很高时通过线程 dump 定位具体哪个线程在做哪个工作占用了过多的资源。 heap dump heap dump 文件是一个二进制文件指定时刻的 Java 堆栈的快照是一种镜像文件它保存了某一时刻 JVM 堆中对象使用情况。 可以通过 Heap Analyzer工具分析 heap dump 文件哪些对象占用了太多的堆栈空间来发现导致内存泄露或者可能引起内存泄露的对象。 thread dump thread dump 文件主要保存的是 java 应用中各线程在某一时刻的运行的位置即执行到哪一个类的哪一个方法哪一个行上。 thread dump 是一个文本文件打开后可以看到每一个线程的执行栈以 stack trace 的方式显示。 通过对 thread dump 的分析可以得到应用是否“卡”在某一点上即在某一点运行的时间太长如数据库查询时长期得不到响应最终导致系统崩溃。 单个的 thread dump 文件一般来说是没有什么用处的因为它只是记录了某一个绝对时间点的情况。比较有用的是线程在一个时间段内的执行情况。 thread dump 文件在分析时特别有效困为它可以看出在先后两个时间点上线程执行的位置。如果发现先后两组数据中同一线程都执行在同一位置则说明此处可能有问题因为程序运行是极快的如果两次均在某一点上说明这一点的耗时是很大的。通过对这两个文件进行分析查出原因进而解决问题。   获取 dump 文件 可以利用 JDK 自带的工具获取 thread dump 文件和 heap dump 文件即 JDK_HOME/bin/ 目录下的 jmap 和 jstack 这两个命令。 1获取 heap dump 文件 ./jmap -dump:formatb,fileheap.hprof 2576这样就会在当前目录下生成 java 应用进程 pid 为 2576 的 heap.hprof 文件这就是 heap dump 文件。 如果我们只需要将 dump 中存活的对象导出那么可以使用 :live 参数 jmap -dump:live,formatb,fileheapLive.hprof 25762获取 thread dump 文件 ./jstack 2576 thread.txt这样会将命令执行结果转储到 thread.txt这就是 thread dump 文件。有了 dump 文件后我们就能借助性能分析工具获取 dump 文件中的信息使用 top -H -p pid 找出某进程中要分析的线程 ID然后将线程 ID 转换为 16 进制后在线程 dump 文件中搜索相关信息。 打开 dump 文件 1使用 JDK 自带的 jhat 命令 jhat 是用来分析 java 堆的命令可以将堆中的对象以 html 的形式显示出来包括对象的数量、大小等等并支持对象查询语言。 jhat -port 5000 heap.hrof当服务启动完成后我们就可以在浏览器中通过 http://localhost:5000/ 进行访问如下所示 2使用 eclipse MAT 工具 一般来说应用程序的 dump 文件都是很大的jdk 自带命令难以分析这些大文件。在实际的生产环境下我们必须要借助第三方工具才能快速打开这些大文件进行分析定位。 安装好 eclipse mat 分析工具后将 dump 文件导入 eclipse点击Leak Suspects找到跟公司有关的代码进行分析。 分析 thread dump 文件 线程 dump 详解 线程的状态 NEW未启动不会出现在 Dump 中。RUNNABLE在虚拟机中执行的。BLOCKED受阻塞并等待在监视器锁。WAITTING无限期等待另一个线程执行特定的操作。TIMED_WAITTING有时限的等候另一个线程执行特定的操作。TERMINATED已退出。 监视器 调用修饰 locked 地址 目标注意临界区对象锁可重入线程状态为 RUNNABLE。waitting to lock 地址 目标还没有获得锁进入区等待线程状态为 BLOCKEDwaitting on 地址 目标获得锁了等待区等待线程状态为 WAITTING,TIMED_WAITTING。parking to wait for 地址 目标线程原语随 current 包出现与 synchronized 体系不同。 线程动作 runnable线程状态为 RUNNABLE。in Object.wait()等待区等待线程状态为 WAITTING 或 TIMED_WAITTING。waitting for monitor entry进入区等待线程状态为 BLOCKED。waitting on condition等待区等待被 park。sleeping休眠的线程调用了 Thread.sleep()。 分析线程 dump 的入手点 进入区等待BLOCKED、waitting to lock、waitting for monitor entry这些词表名代码层面已经存在冲突。 持续进行的 IO一般来说被捕捉到的 runnable 的 IO 调用都是有问题的如 runnable 中有 JDBC 链接的代码。 非线程调度的等待区等待in Object.wait()情况 1 可能会导致这个情况造成大量线程堆积。 “死锁”问题的解决办法 在最可能死锁的时间点制作 dump。 找出引起大量线程阻塞的线程。 找出该线程阻塞的原因。 阅读代码遍历其他阻塞或等待的线程以及它之前的调用是否会造成这个线程的等待。 注意排除 GC 干扰Full GC 时所有线程都会被阻塞住。 查看线程 dump 时首先查看内存使用情况。使用命令“-verbose:gc”观察是否有 Full GC 字样。 分析 heap dump 文件 什么情况下需要分析堆 Dump 内存不足、GC 异常、怀疑代码内存泄漏这时需要制作堆 Dump找出生命周期的错误关联对象以及相关代码。 JVM 内存模型 年轻代Young Generation包括Eden space、From space、To space年老代Old Generation永久代PermGen space 两种 GC YoungGen GCMinor GCFull GCMajor GC 常见错误 out of MemoryError:GC overhead limit exceed回收时间占系统运行时间的 98% 以上极有可能是内存泄漏导致的。 案例分析JVM 堆内存溢出 JVM 堆内存回收详细过程图解从下图可以很清晰的看到old 区空间占满后会进行一次 FGC称为全量 GCFGC 回收后如果 old 区空间还是不能容纳新生成对象那么便会产生 java 堆内存溢出JAVA HEAP OOM。 性能问题发现过程 查看服务器上报错日志发现有如下报错信息java.lang.OutOfMemoryError: Java heap space根据报错信息确定是 jvm 堆内存空间不够导致于是使用 jvm 命令查看下图所示发现此时 old 区内存空间已经被占满了。 同时使用 jvisualvm 监控工具也发现 old 区空间被占满如下图所示单位为百分比整个 heap 区空间已经无法再容纳新对象进入。 建议考虑大量数据一次性写入内存场景。 案例分析持久代内存溢出 PermSpace 主要是存放静态的类信息和方法信息、静态的方法和变量、final 标注的常量信息等。 现象 压测某系统接口压测前1分钟左右 TPS 400 多之后 TPS 直降为零后台报错日志java.lang.OutOfMemoryError:PermGenspace通过 jvm 监控工具查看持久代perm区空间被占满而 Old 区空闲。 问题定位 通过注释代码块定位问题考虑到 perm 区溢出大部分跟类对象大量创建有关故锁定问题在序列化框架使用可能有问题。 获取 JVM dump 文件。 安装 eclipse mat 分析工具。 将 dump 文件导入 eclipse点击Leak Suspects找到跟公司有关的代码进行分析。 解决方案 跟开发沟通后选择去掉 msgpack0.6 版本框架采用 java 原生序列化框架。修改后系统 tps 稳定在 400 多gc 情况正常。 修复前 修复后 类似问题如何避免 去掉项目无用 jar 包。避免大量使用类对象、大量使用反射。 案例分析频繁 FGC 现象系统某接口频繁 FGC。 问题排查及解决方案 先查 JVM 内存信息找可疑对象命令为jmap -histo 从内存对象实例信息中发现跟 mysql 连接有关然后检测 mysql 配置信息 bean iddataSource classorg.springframework.jdbc.datasource.DriverManagerDataSource发现系统采用的是 spring 框架的数据源没有用连接池。 使用连接池的好处连接复用减少连接重复建立和销毁造成的大量资源消耗。然后换做 hikaricp 连接池做对比测试 bean iddataSource classcom.zaxxer.hikari.HikariDataSource压测半小时未出现 fgc问题得到解决。 类似问题如何避免 研发规范统一 DB 连接池避免研发误用。减少大对象、临时对象使用。 案例分析减少 mirror GC 现象 假设现在有亿级流量电商的抢购活动活跃用户为 500 万付费转化率为 10%。活跃时间在抢购的前几分钟假设每秒产生 1000 单而每台 Tomcat 的最高并发支持数为 500。现有三台服务器均为 4 核 8g每台服务器均部署 Tomcat使用 nginx 做负载均衡。 有 300 单落在服务器 1 上每单所在堆空间大小为 1Kb每秒大约产生 300Kb 的堆对象。可以使用 lucene 来动态计算 javabean 所在堆空间的大小。下单还会产生其他对象比如优惠券、库存、积分等此时放大 20 倍也就是每秒产生 6000Kb 的对象。假设还会有订单查询的操作此时再放大 10 倍也就是每秒产生约 58MB 的对象。 此时堆初始值大小和最大值大小均为 3072MB老年代大小为 2048MB新生代大小为 1024MBEden 区大小为 819MBs0 和 s1 区大小均为 102MB。819Mb / 58Mb 14 秒即大约 14 秒 Eden 区爆满触发 mirror Gc此时停止应用程序的线程。 优化 因而此时需要调整 JVM 的配置参数老年代大小为 1024MB新生代大小为 2048MBEden 区大小为 1638MBs0 和 s1 区大小均为 204MB。1638Mb/ 58Mb 28秒这样能减少 mirror Gc从而达到优化的效果。但更多的优化可根据实际线上 jvm 运行情况来看。 框架使用不当 案例分析错误使用框架提供的 API 某系统本身业务逻辑处理能力很快研发本机自测 tps 可以到达 2w 多但是接入到 framework 框架后TPS 最高只能到达 300 左右而且系统负载很低。 问题排查 这种现象说明系统可能是堵在了某块方法上根据这种情况一般采用线程 dump 的方式来查看系统具体哪些线程出现异常情况。 通过线程 dump 发现 TIMED_WAITING状态的业务线程占比很高。 # 线程的状态 * NEW未启动不会出现在 Dump 中。 * RUNNABLE在虚拟机中执行的。 * BLOCKED受阻塞并等待在监视器锁。 * WAITTING无限期等待另一个线程执行特定的操作。 * TIMED_WAITTING有时限的等候另一个线程执行特定的操作。 * TERMINATED已退出。根据线程 dump 信息找到公司包名开头的信息然后从下往上查看线程 dump 信息从信息中我们可以看到 framework.servlet.fServlet.doPost框架 api 封装了 servletdopost 方法做了某些操作。framework.servlet.fServlet.execute框架 api 执行 servelt。framework.process.fProcessor.process框架 api 进行自身逻辑处理。framework.filter.impl.AuthFilter.before框架使用过滤器进行用户权限过滤。。。然后就是进行 http 请求操作。 由此判断就是在框架进行权限校验这块堵住了。之后跟开发沟通这块的问题即可。 问题原因 性能测试是验证 A 系统的处理能力但是在压测程序里A 系统却调用了权限校验系统由于权限校验系统处理能力只有 300 左右从而拖慢了整个系统处理能力。 因此需要在压测过程中关闭对权限校验系统调用只压 A 系统这样才能压测出 A 真实的处理能力。 解决方案 去掉对 B 系统调用即去掉权限校验。 Api(authtrue) 改为 Api(authfalse)案例分析日志框架使用不当 某系统添加 LOGBACK 日志框架输出日志日志级别为 INFO后TPS 从 1000 降到 200 多 从 JVISUALVM 工具看到有大量业务线程处于 BLOCKED 状态 优化方案 日志降级、将日志级别改为 warn减少日志输出量。 后续建议 合理设置日志级别、精简日志输出。 合理设置日志刷盘方式同步 or 异步。 对于 DEBUG、INFO 日志打印、需要先判断日志级别if(LOGGER.isDebugEnabled()){do log} 。 OS 内存溢出 问题现象 某系统线上故障系统假死无法提供服务服务器 ssh 无法登录。 问题根因 系统使用堆外内存操作系统内核占用 cache 内存当 cache 内存占满后无法释放导致物理内存 OOMOut Of Memory。 为什么会 OOM   为什么会没有内存了呢原因不外乎有两点 分配的少了比如虚拟机本身可使用的内存一般通过启动时的 JVM 参数指定太少。 应用用的太多并且用完没释放浪费了。此时就会造成内存泄露或者内存溢出。 优化方案 通过优化 linux 操作系统内核参数min_free_kbytes 自动化测试相关教程推荐 2023最新自动化测试自学教程新手小白26天入门最详细教程,目前已有300多人通过学习这套教程入职大厂_哔哩哔哩_bilibili 2023最新合集Python自动化测试开发框架【全栈/实战/教程】合集精华学完年薪40W_哔哩哔哩_bilibili 测试开发相关教程推荐 2023全网最牛字节测试开发大佬现场教学从零开始教你成为年薪百万的测试开发工程师_哔哩哔哩_bilibili postman/jmeter/fiddler测试工具类教程推荐 讲的最详细JMeter接口测试/接口自动化测试项目实战合集教程学jmeter接口测试一套教程就够了_哔哩哔哩_bilibili 2023自学fiddler抓包请一定要看完【如何1天学会fiddler抓包】的全网最详细视频教程_哔哩哔哩_bilibili 2023全网封神B站讲的最详细的Postman接口测试实战教学小白都能学会_哔哩哔哩_bilibili 总结 光学理论是没用的要学会跟着一起敲要动手实操才能将自己的所学运用到实际当中去这时候可以搞点实战案例来学习。 如果对你有帮助的话点个赞收个藏给作者一个鼓励。也方便你下次能够快速查找。 如有不懂还要咨询下方小卡片博主也希望和志同道合的测试人员一起学习进步 在适当的年龄选择适当的岗位尽量去发挥好自己的优势。 我的自动化测试开发之路一路走来都离不每个阶段的计划因为自己喜欢规划和总结 测试开发视频教程、学习笔记领取传送门

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

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

相关文章

网站数据流程h5 和手机网站

开篇:探索稀疏多视图图像的3D场景重建与新视角合成的挑战 3D场景重建和新视角合成是计算机视觉领域的一项基础挑战,尤其是当输入图像非常稀疏(例如,只有两张)时。尽管利用神经场景表示,例如场景表示网络&a…

做公益网站的原因做电商网站的设计思路有什么意思

Three场景实现多个物体的合并 目的 产品需求是让物体的光柱墙包含一个多边形的区域,二而我的多边形只能使用原型,方向,多边形。那么再研究的时候就需要将这些多边形合并成为一个形状,那么就行实现了。 原先的图形 如上图,是两个mesh组成的。首先寻找mesh合并的方法。 第…

深圳住房网站app北京网络职业学院怎么样

1. 数学研究 1.1. 数学研究变得更为艰难了 1.1.1. 学科分支越发密集,问题越发复杂 1.1.2. 攻读博士学位的3年时间,只够去理解导师所给题目的含义 1.1.3. 随后,再花费数年时间去研究、探索,运气不错的话,会得到一些…

梅州市建设局网站素材中国官网

微信小程序css 华文琥珀Brian Goetz最近的消息欢迎来到琥珀! 介绍Project Amber ( OpenJDK的一部分, 最初于1月提出 )。 Goetz通过介绍“欢迎使用Amber项目,这是我们面向特定生产力的Java语言JEP的孵化场”的介绍打开了…

网站建设 岗位职责 智联wordpress插件转换移动浏览

什么是计算机视觉 近年来,计算机视觉 (Computer Vision,简称CV) 不断普及,已成为人工智能 (AI) 增长最快的领域之一。计算机视觉致力于使计算机能够识别和理解图像和视频中的物体和人。 计算机视觉应用程序使用来自传感设备、人工智能、机器…

三门峡河南网站建设常德论坛尚一网市民留言

目录 数据隔离/权限控制 用户/权限/部门/岗位 ​数据隔离 mybatis的maaper写法 注解和切面 前端路由拦截 已知若依单体的前端采用vue-element-admin,在前端的专栏系列vue-element-admin的动态路由已详细拆解,其最大特点是使用后端返回数据控制前端…

设计教程网站推荐网站建设需要要多少钱

概览 在构建事件驱动应用时,人们面临着两大挑战:1)低延迟处理大量数据;2)实现流数据的实时摄取和转换。 结合 RisingWave 的流处理功能和 ScyllaDB 的高性能 NoSQL 数据库,可为构建事件驱动应用和数据管道…

购物网站分为几个模块wordpress如何采集优酷

前面学习函数时已经知道必须先存在一个函数然后才能使用,且这个函数的位置还要在 main()函数之前,否则的话编译时会报错。但我们写程序时,main() 函数是程序入口,程序的主要部分都在 main() 函数中,且其它函数也都要通…

企业网站案列网站建设 海拉尔

一、先来看一个需求 Spring MVC也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能,比如对临时文件的清除,或者对某些ip地址进行拦截器. 二、springMVC自定义拦截器介绍 (1)需要实现一个接口 HandlerInterceptor. (…

缙云企业网站建设优化设计三年级上册答案

在笔者上一篇文章《内核MDL读写进程内存》简单介绍了如何通过MDL映射的方式实现进程读写操作,本章将通过如上案例实现远程进程反汇编功能,此类功能也是ARK工具中最常见的功能之一,通常此类功能的实现分为两部分,内核部分只负责读写…

厦门建设网站建站做网站费用怎么记分录

一、使用中文字符 在python源码中如果使用了中文字符,运行时会有错误,解决的办法是在源码的开头部分加入字符编码的声明,下面是一个例子:#!/usr/bin/env python# -*- coding: cp936 -*-Python Tutorial中指出,python的…

网站建设 300元网络营销常见术语

前些天发现了十分不错的人工智能学习网站,通俗易懂,风趣幽默,没有广告,分享给大家,大家可以自行看看。(点击跳转人工智能学习资料) 微信公众号:创享日记 发送关键词:前馈…

厦门做网站找谁苏州专业高端网站建设企业

首先进入PE,在PE下找到你的系统ISO镜像,解压缩,然后将镜像里的boot文件夹、sources文件夹和bootmgr文件提取出来,然后复制到你要安装的分区(比如c盘),接下来拔下U盘,重新启动计算机&…

酒店网站建设公司排名wordpress站点链接打不开网址

在mysql中,会有相关的like关键词,并且默认的是忽略大小写的。但是在postgresql和kingbase中,只有ilike关键字,并且默认是大小写敏感的。当我们使用mybatisplus的时候,默认提供的api也只有like()。这里提供一种方式来对…

成都哪个公司做网站英文企业网站建设

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 简单的场景设置 步骤 1 打开 3ds Max。 打开 3ds Max 步骤 2 我将向您展示风铃背后的动态 通过简单的场景设置进行模拟。一旦你有了这个想法,你就可以应用这个 技术到复杂的风铃结构。 基…

网站开发常用的技术建设电商网站的总结

$dir"C:/THsoft";//这是一个目录地址 也是根目录if (is_dir($dir)){//判断$dir是否是一个目录if ($dhopendir($dir)){//dh变量用来接收opendir的返回信息 如果为真 则执行whilewhile (($filereaddir($dh))!false){ //readdir()函数会返回一个文件的名称的echo …

网站多少流量够用免费正规大数据查询平台

目录 1.网络爬虫的作用(人话): 2.使用的工具 3.不使用程序进行网页信息的获取的操作步骤 4.如何使用程序来进行上述操作 1.打开浏览器 2.输入网址 3.发送请求 4.获取响应 5.判断响应是否成功 6.获取响应里需要的内容 7.记得最后关…

长春网站推广优化传奇世界页游

strtok函数是字符串函数库中的一个函数,函数原型如下:char *strtok(char s[], const char *delim);作用:分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。例如:"hello,hi:what?is!the.matter;&…

网站建设步骤邯郸网站制作个人

今年6月,文件共享工具MOVEit Transfer曾曝出SQL 注入漏洞,能让远程攻击者访问其数据库并执行任意代码。最近,MOVEit Transfer 母公司Progress Software又披露了三个新漏洞。 这三个漏洞分别是 CVE-2023-36932、CVE-2023-36933 和 CVE-2023-36…

营销型网站建设计划书软件开发过程五个步骤

原题链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-array/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 用双指针算法,定义两个变量src和dst,一开始让src和dst指向num[ ]数组的第一个元素&a…