性能测试:系统架构性能优化思路

今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。
系统性能问题分析流程

我们首先来分析下如果一个业务系统上线前没有性能问题,而在上线后出现了比较严重的性能问题,那么实际上潜在的场景主要来自于以下几个方面。
业务出现大并发的访问,导致出现性能瓶颈
上线后的系统数据库数据日积月累,数据量增加后出现性能瓶颈
其它关键环境改变,比如我们常说的网络带宽影响
正是由于这个原因,当我们发现性能问题的时候,首先就需要判断是单用户非并发状态下本身就有性能问题,还是说在并发状态才存在性能问题。对于单用户性能问题往往比较容易测试和验证,对于并发性能问题我们可以在测试环境进行加压测试和验证,以判断并发下的性能。
如果是单用户本身就存在性能问题,那么大部分问题都出在程序代码和SQL需要进一步优化上面。如果是并发性能问题,我们就需要进一步分析数据库和中间件本身的状态,看是否需要对中间件进行性能调优。
在加压测试过程中,我们还需要对CPU,内存和JVM进行监控,观察是否存在类似内存泄漏无法释放等情况,即并发下性能问题本身也可能是代码本身原因导致性能异常。
性能问题影响因素分析

对于性能问题影响因素,简单来说包括了硬件环境,软件运行环境和软件程序三个方面的主要内容。下面分别再展开说明下。
硬件环境
硬件环境就是我们常说的计算,存储和网络资源。
对于服务器的计算能力,一般来说厂家都会提供TPMC参数作为一个参考数据,但是我们实际看到相同TPMC能力下的X86服务器能力仍然低于小型机的能力。
除了服务器的计算能力参数,另外一个重点就是我们说的存储设备,影响到存储的重点又是IO读写性能问题。有时候我们监控发现CPU和内存居高不下,而真正的瓶颈通过分析反而发现是由于IO瓶颈导致,由于读写性能跟不上,导致大量数据无法快速持久化并释放内存资源。

比如在Linux环境下,本身也提供了性能监控工具方便进行性能分析。比如常用的iostat,ps,sar,top,vmstat等,这些工具可以对CPU,内存,JVM,磁盘IO等进行性能监控和分析,以发现真正的性能问题在哪里。
比如我们常说的内存使用率持续告警,你就必须发现是高并发调用导致,还是JVM内存泄漏导致,还是本身由于磁盘IO瓶颈导致。
对于CPU,内存,磁盘IO性能监控和分析的一个思路可以参考:

运行环境-数据库和应用中间件
数据库和应用中间件性能调优是另外一个经常出现性能问题的地方。
数据库性能调优
拿Oracle数据库来说,影响数据库性能的因素包括:系统、数据库、网络。数据库的优化包括:优化数据库磁盘I/O、优化回滚段、优化Rrdo日志、优化系统全局区、优化数据库对象。

要调整首先就需要对数据库性能进行监控
我们可以在init.ora参数文件中设置TIMED_STATISTICS=TRUE 和在你的会话层设置ALTER SESSION SET STATISTICS=TRUE 。运行svrmgrl 用 connect internal 注册,在你的应用系统正常活动期间,运行utlbstat.sql 开始统计系统活动,达到一定的时间后,执行utlestat.sql 停止统计。统计结果将产生在report.txt 文件中。
数据库性能优化应该是一个持续性的工作,一个方面是本身的性能和参数巡检,另外一个方面就是DBA也会经常提取最占用内存的低效SQL语句给开发人员进一步分析,同时也会从数据库本身的以下告警KPI指标中发现问题。
比如我们可能会发现Oracle数据库出现内存使用率高的告警,而通过检查会发现是产生了大量的Redo日志导致,那么我们就需要从程序上进一步分析为何会产生如此多的回滚。
应用中间件性能分析和调优
应用中间件容器即我们常说的Weblogic, Tomcat等应用中间件容器或Web容器。应用中间件调优一个方面是本身的配置参数优化设置,一个方面就是JVM内存启动参数调优。
对于应用中间件本身的参数设置,主要包括了JVM启动参数设置,线程池设置,连接数的最小最大值设置等。如果是集群环境,还涉及到集群相关的配置调优。
对于JVM启动参数调优,往往也是应用中间件调优的一个关键点,但是一般JVM参数调优会结合应用程序一起进行分析。

比如我们常见的JVM堆内存溢出,如果程序代码没有内存泄漏问题的话,我就需要考虑调整JVM启动时候堆内存设置。在32位操作系统下只能够设置到4G,但是在64位操作系统下已经可以设置到8G甚至更大的值。
其中JVM启动的主要控制参数说明如下:
-Xmx #设置最大堆空间
-Xms #设置最小堆空间
-XX:MaxNewSize #设置最大新生代空间
-XX:NewSize #设置最小新生代空间
-XX:MaxPermSize #设置最大永久代空间(注:新内存模型已经替换为Metaspace)
-XX:PermSize #设置最小永久代空间(注:新内存模型已经替换为Metaspace)
-Xss #设置每个线程的堆栈大小
那么这些值究竟设置多大合适,具体来讲:

Java整个堆大小设置,Xmx 和 Xms设置为老年代存活对象的3-4倍,即FullGC之后的老年代内存占用的3-4倍。永久代 PermSize和MaxPermSize设置为老年代存活对象的1.2-1.5倍。
年轻代Xmn的设置为老年代存活对象的1-1.5倍。
老年代的内存大小设置为老年代存活对象的2-3倍。
注意在新的JVM内存模型下已经没有PermSize而是变化为Metaspace,因此需要考虑Heap内存和Metaspace大小的配比,同时还需要考虑相关的垃圾回收机制是采用哪种类型等。
对于JVM内存溢出问题,我前面写过一篇专门的分析文章可以参考。
从表象到根源-一个软件系统JVM内存溢出问题分析解决全过程

软件程序性能问题分析
在这里首先要强调的一点就是,当我们发现性能问题后首先想到的就是扩展资源,但是大部分的性能问题本身并不是资源能力不够导致,而是我们程序实现上出现明显缺陷。
比如我们经常看到的大量循环创建连接,资源使用了不释放,SQL语句低效执行等。
为了解决这些性能问题,最好的方法仍然是在事前控制。其中包括了事前的代码静态检查工具的使用,也包括了开发团队对代码进行的Code Review来发现性能问题。
所有已知的问题都必须形成开发团队的开发规范要求,避免重复再犯。
业务系统性能问题扩展思考
对于业务系统的性能优化,除了上面谈到的标准分析流程和分析要素外,再谈下其它一些性能问题引发的关键思考。
上线前的性能测试是否有用?
有时候大家可能觉得奇怪,为何我们系统上线前都做了性能测试,为何上线后还是会出现系统性能问题。那么我们可以考虑下实际上我们上线前性能测试可能存在的一些无法真实模拟生产环境的地方,具体为:
硬件能否完全模拟真实环境?最好的性能测试往往是直接在搭建完成的生产环境进行。
数据量能否模拟实际场景?真实场景往往是多个业务表都已经存在大数据量的积累而非空表。
并发能否模拟真实场景?一个是需要录制复合业务场景,一个是需要多台压测机。
而实际上我们在做性能测试的时候以上几个点都很难真正做到,因此要想完全模拟出生产真实环境是相当困难的,这也导致了很多性能问题是在真正上线后才发现。
系统本身水平弹性扩展是否完全解决性能问题?
第二个点也是我们经常谈的比较多的点,就是我们的业务系统在进行架构设计的时候,特别是面对非功能性需求,我们都会谈到系统本身的数据库,中间件都采用了集群技术,能够做到弹性水平扩展。那么这种弹性水平扩展能力是否又真正解决了性能问题?
实际上我们看到对于数据库往往很难真正做到无限的弹性水平扩展,即使对于Oracle RAC集群往往也是最多扩展到单点的2到3倍性能。对于应用集群往往可以做到弹性水平扩展,当前技术也比较成熟。
当中间件能够做到完全弹性扩展的时候,实际上仍然可能存在性能问题,即随着我们系统的运行和业务数据量的不断积累增值。实际上你可以看到往往非并发状态下的单用户访问本身就很慢,而不是说并发上来后慢。因此也是我们常说的要给点,即:
单点访问性能正常的时候可以扩展集群来应对大并发状态下的同时访问
单点访问本身性能就有问题的时候,要优先优化单节点访问性能
业务系统性能诊断的分类
对于业务系统性能诊断,如果从静态角度我们可以考虑从以下三个方面进行分类
操作系统和存储层面
中间件层面(包括了数据库,应用服务器中间件)
软件层面(包括了数据库SQL和存储过程,逻辑层,前端展现层等)
那么一个业务系统应用功能出现问题了,我们当然也可以从动态层面来看实际一个应用请求从调用开始究竟经过了哪些代码和硬件基础设施,通过分段方法来定位和查询问题。
比如我们常见的就是一个查询功能如果出现问题了,首先就是找到这个查询功能对应的SQL语句在后台查询是否很慢,如果这个SQL本身就慢,那么就要优化优化SQL语句。如果SQL本身快但是查询慢,那就要看下是否是前端性能问题或者集群问题等。
软件代码的问题往往是最不能忽视的一个性能问题点
对于业务系统性能问题,我们经常想到的就是要扩展数据库的硬件性能,比如扩展CPU和内存,扩展集群,但是实际上可以看到很多应用的性能问题并不是硬件性能导致的,而是由于软件代码性能引起的。对于软件代码常见的性能问题我在以往的博客文章里面也谈过到,比较典型的包括了。
循环中初始化大的结构对象,数据库连接等
资源不释放导致的内存泄露等
没有基于场景需求来适度通过缓存等方式提升性能
长周期事务处理耗费资源
处理某一个业务场景或问题的时候,没有选择最优的数据结构或算法
以上都是常见的一些软件代码性能问题点,而这些往往需要通过我们进行Code Review或代码评审的方式才能够发现出来。因此如果要做全面的性能优化,对于软件代码的性能问题排查是必须的。
通过IT资源监控或APM应用工具来发现性能问题

对于性能问题的发现一般有两条路径,一个就是通过我们IT资源的监控,APM的性能监控和预警来提前发现性能问题,一个是通过业务用户在使用过程中的反馈来发现性能问题。
APM应用性能管理主要指对企业的关键业务应用进行监测、优化,提高企业应用的可靠性和质量,保证用户得到良好的服务,降低IT总拥有成本(TCO)。
资源池-》应用层-》业务层
这个可以理解为APM的一个关键点,原有的网管类监控软件更多的是资源和操作系统层面,包括计算和存储资源的使用和利用率情况,网络本身的性能情况等。但是当要分析所有的资源层问题如何对应到具体的应用,对应到具体的业务功能的时候很难。
传统模式下,当出现CPU或内存满负荷的时候,如果要查找到具体是哪个应用,哪个进程或者具体哪个业务功能,哪个sql语句导致的往往并不是容易的事情。在实际的性能问题优化中往往也需要做大量的日志分析和问题定位,最终才可能找到问题点。
比如在我们最近的项目实施中,结合APM和服务链监控,我们可以快速的发现究竟是哪个服务调用出现了性能问题,或者快速的定位出哪个SQL语句有验证的性能问题。这个都可以帮助我们快速的进行性能问题分析和诊断。
资源上承载的是应用,应用本身又包括了数据库和应用中间件容器,同时也包括了前端;在应用之上则是对应到具体的业务功能。因此APM一个核心就是要将资源-》应用-》功能之间进行整合分析和衔接。
而随着DevOps和自动化运维的思路推进,我们更加希望是通过APM等工具主动监控来发现性能问题,对于APM工具最大的好处就是可以进行服务全链路的性能分析,方便我们发现性能问题究竟发生在哪里。比如我们提交一个表单很慢,通过APM分析我们很容易发现究竟是调用哪个业务服务慢,或者是处理哪个SQL语句慢。这样可以极大的提升我们性能问题分析诊断的效率。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!

相关文章:
性能测试:系统架构性能优化思路
今天谈下业务系统性能问题分析诊断和性能优化方面的内容。这篇文章重点还是谈已经上线的业务系统后续出现性能问题后的问题诊断和优化重点。 系统性能问题分析流程 我们首先来分析下如果一个业务系统上线前没有性能问题,而在上线后出现了比较严重的性能问题&#x…...
python字符串格式化
字符串格式化 # 2023年11月16日 星期四 y 2023 m 11 d 16 w 四 s %d年%d月%d日 星期%s%(y,m,d,w) print(s) s {}年{}月{}日 星期{}.format(y,m,d,w) print(s) s f{y}年{m}月{d}日 星期{w} print(s)...
Linux的基本指令(二)
目录 前言 学前补充 touch指令 mkdir指令 rmdir指令 rm指令 通配符* man指令 cp指令 mv指令(重要) 补充内容: 1、如何快速在Linux中写出代码 2、如何看待如此多的Linux指令 cat指令 前言 关于Linux的基本指令我们会分三到四篇文章进行分析,…...
每日一题--寻找重复数
蝶恋花-王国维 阅尽天涯离别苦, 不道归来,零落花如许。 花底相看无一语,绿窗春与天俱莫。 待把相思灯下诉, 一缕新欢,旧恨千千缕。 最是人间留不住,朱颜辞镜花辞树。 目录 题目描述: 思路分析…...
C#,《小白学程序》第二十二课:大数的乘法(BigInteger Multiply)
1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的(加减乘除)四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// </summary> p…...
kafka,RabbitMQ,RocketMQ,他们之间的区别,架构,如何保证消息的不丢失,保证不重复消费,保证消息的有序性
文章目录 Kafka、RabbitMQ、RocketMQ 之间的区别是什么?性能数据可靠性服务可用性功能 RabbitMQ如何保证消息不丢失?Kafka 的架构说一下?Kafka 怎么保证消息是有序的?Kafka 怎么解决重复消费?Kafka 怎么保证消息不丢失…...
uni-app中vue3+setup实现下拉刷新、上拉加载更多效果
在小程序或各类app中,下拉刷新和上拉加载更多是极为常见和使用非常频繁的两个功能,通过对这两个功能的合理使用可以极大的方便用户进行操作。 合理的设计逻辑才能更容易挽留住用户,因为这些细节性的小功能点就变得极为重要起来。 那么在uni…...
微服务实战系列之Nginx(技巧篇)
前言 今天北京早晨竟然飘了一些“雪花”,定睛一看,似雪非雪,像泡沫球一样,原来那叫“霰”。 自然中,雨雪霜露雾,因为出场太频繁,认识门槛较低,自然不费吹灰之力,即可享受…...
好工具|datamap,一个好用的地图可视化Excel插件,在Excel中实现地理编码、拾取坐标
在做VRP相关研究的时候,需要对地图数据做很多处理,比如地理编码,根据“重庆市沙坪坝区沙正街174号”这样的一个文本地址知道他的经纬度;再比如绘制一些散点图,根据某个位置的经纬度在地图上把它标注出来。还有有的时候…...
Java——继承
继承是面向对象编程的三大特征之一,它让我们更加容易实现对已有类的扩展、更加容易实现对现实世界的建模。 继承有两个主要作用: 代码复用,更加容易实现类的扩展方便建模 继承的实现 继承让我们更加容易实现对类的扩展。比如我们定义了人…...
十、sdl显示yuv图片
前言 SDL中内置加载BMP的API,使用起来会更加简单,便于初学者学习使用SDL 如果需要加载JPG、PNG等其他格式的图片,可以使用第三方库:SDL_image 测试环境: ffmpeg的4.3.2自行编译版本windows环境qt5.12sdl2.0.22&…...
Docker Nginx容器部署vue项目
Docker Nginx容器部署vue项目 文章目录 Docker Nginx容器部署vue项目1. 前提2. 下载nginx镜像3. 编写nginx.conf配置文件4. 编写构建命令5. vue项目上传 1. 前提 Docker服务已部署 2. 下载nginx镜像 首先查看有没有nginx镜像 docker images没有的情况下再进行下载 docker …...
【深度学习】如何找到最优学习率
经过了大量炼丹的同学都知道,超参数是一个非常玄乎的东西,比如batch size,学习率等,这些东西的设定并没有什么规律和原因,论文中设定的超参数一般都是靠经验决定的。但是超参数往往又特别重要,比如学习率&a…...
详解—C++三大特性——多态
目录 一. 多态的概念 1.1 概念 二. 多态的定义及实现 2.1多态的构成条件 2.2 虚函数 2.3虚函数的重写 2.3.1虚函数重写的两个例外: 1. 协变(基类与派生类虚函数返回值类型不同) 2. 析构函数的重写(基类与派生类析构函数的名字不同) 2.4 C11 override 和 f…...
用idea搭建一个spring cloud微服务项目
以下是使用 IntelliJ IDEA 搭建 Spring Cloud 微服务项目的步骤: 创建一个新的 Maven 项目。 在 pom.xml 文件中添加以下依赖: <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-…...
SpringBoot——启动类的原理
优质博文:IT-BLOG-CN SpringBoot启动类上使用SpringBootApplication注解,该注解是一个组合注解,包含多个其它注解。和类定义SpringApplication.run要揭开SpringBoot的神秘面纱,我们要从这两位开始就可以了。 SpringBootApplicati…...
Rust语言入门教程(七) - 所有权系统
所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源,也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统,才使得编译器能够提前暴露代码中的错误,并给出我们必要且精准的错误提示。 所有权系统的三个规则…...
【MATLAB源码-第89期】基于matlab的灰狼优化算法(GWO)无人机三维路径规划,输出做短路径图和适应度曲线
操作环境: MATLAB 2022a 1、算法描述 灰狼优化算法(Grey Wolf Optimizer, GWO)是一种模仿灰狼捕食行为的优化算法。灰狼是群居动物,有着严格的社会等级结构。在灰狼群体中,通常有三个等级:首领ÿ…...
线程池的饱和策略有哪些?
线程池的饱和策略是指当线程池中的任务队列已满时,线程池如何处理新提交的任务。常见的饱和策略有以下几种: 阻塞策略 阻塞策略是指当线程池中的任务队列已满时,新提交的任务会等待队列中有空闲位置后再执行。这种策略可以避免过多的任务被…...
Git设置多个仓库同时推送
Git设置多个仓库同时推送 添加 在Git中,有时我们需要将同一份代码推送到不同的远程仓库,只是URL地址不同。 下面是一种优化的方法来设置多个仓库同时推送: # 添加一个新的远程仓库 git remote set-url --add origin2 新的仓库地址这样&am…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

