题记:个人从事性能专项8年+,对项目的性能过程还算有一定的见解能力。最近一年有机会领导并主导性能测试的发展和建设工作,让我很多想法可以逐步落地(之前受上面领导和KPI的限制,很多事情不能真正的按照自己的想法去做。)
先看下我的大盘规划图:
(双击查看大图)
![73062bc8b2a84b2d175239643ff55449.png](https://i-blog.csdnimg.cn/blog_migrate/126c019fdf71333eebbf0af40f7ca736.jpeg)
针对以上规范,我先说明两点:
1、后端的细节部分,要根据实际的项目需求调整。
如考核和需求模板内容(笔者工作环境特殊,有一部分是外部负责压测性能的,故需要针对他们的方案和报告进行评审卡关)
2、图上各种平台化的编号,就是我在实际项目中实现的顺序(优先级)。
细心的读者会发现我们把性能压测平台放在最后,为此我专门表达下我的观点:
A、优先做可以花20%的时间完成能提升80%效率的事情!
性能平台不是小事,做好一个可用、易用、实用性能平台更不是一件容易的事情!笔者从华为、携程、网易,都接触过过也自行创建过性能压测平台,但真正做到好用的平台,我可以负责的说目前没有!缺点都十分明显,限制也颇多。有的时候使用这些平台,甚至还不如自己直接用JMeter方便(JMeter做了十几年,你平台才做了多久?)!
而性能平台先做到可用、易用这水平(还得符合自己的压测场景,比如在网易经常需要两三百台的压测机发压,那么平台对压测机和报表的采集实时性要求就很高了),不是说随随便便的团队都能在短时间内完成的!真的说做出一套符合公司场景使用的性能压测平台,2人左右的测试开发团队,能在2年做到70分已经很不错了!
显然,这上面的花销可是远超20%的时间了,提升的效率嘛,继续看下面。
B、“我们做个性能平台,谁都可以压测”--伪命题!!!
在我之前的性能培训中,我多次强调过,性能测试是一项看重过程的测试!
如果真的是那么简单,Apache出个压测平台应该不是什么难事,所有的性能压测人员就可以下岗了……显然现实不是如此,是因为大部分性能测试过程,都会发现很多性能问题,那么这个期间,
第一你要有察觉到性能问题发生的能力;
第二就是要能定位到性能问题的原因能力。
显然这两点,才是性能测试过程中,最难,最有技术含量的地方。而并不是在脚本的创建和点下按钮的执行上!平台在这两点并不能提高多少效率,甚至平台化就意味着限制化(JMeter的灵活度相信熟悉的人都知道),实际过程中二次开发的脚本、各种依赖或者插件的脚本,平台的兼容性,我只能呵呵了……
C、性能压测平台的意义
那么问题来了,性能压测平台的意义在哪里?
从我个人的理解角度,平台出现的目的就是要么提升效率,要么规范过程!
I、脚本的统一管理;
II、测试过程的数据和历史记录保存;
III、规范的执行过程(避免有人少测或者没测);
IV、针对高并发的业务需要,更好统一管理压测机和压测服务器。
就我目前所负责的团队而言,我们的归档要求很清晰,所以I、II、III,在没有平台的前提下,我们也做到了很有秩序和条例的管理。(你要什么项目的脚本、数据、方案、报告,我可以在一两分钟内给你找到。)
而针对IV点,如果工作环境,真的经常需要少则三五台,多则百十来台的压测机,那么平台化就变成了必需,毕竟你手动去用JMeter远程一两台机器还可以,但三五台以上,就并非那么方便了,此外,压测结果的聚合报表的实时展示能力,也存在考量!
但,单台4C8G的window压测机,JMeter支持1500-2000并发的压力,所以我相信除了大部分的公司业务都是完全够用的(毕竟我们大部分也都是在测试环境下压测的。)所以,IV点对我而言,是完全不存在的。
恕我直言:很多性能压测平台出来后,实用和易用性并不高,这些平台诞生的目的仅仅是为了KPI,为了给领导看罢了……
-------------------------------------------正文开始-------------------------------------------
清楚了上面的目的,那么我们就来看看我这边,怎么将一个性能为0的传统业的公司,快速走向规范化、高效化(不到1年的时间,我有信心说,我们现在的性能流程和专业度,不会比外面的任何互联网公司差什么,除了TPS不是一个量级外),让游击队逐渐拥有正规军的战斗力!
性能组成员人数:>4人
性能水平:2-3年性能专项经验(但性能水平一般,认知片面)
外围环境:开发人员平均水平低下(很多都是毕业1-2年的新人,代码质量可想而知),(性能方面薄弱)
负责业务:全集团业务,种类繁多,架构参差不齐且杂乱
面对的问题:
1、公司运维能力薄弱,环境信息杂乱,监控不够专业;
2、组内成员技术水平低下,性能短板太多!
3、项目流程随意,性能随意,毫无规范可言。
针对第3点,我花了半年的时间推行性能测试流程规范,定制了性能测试方案和性能报告的要求(同时约束完全应付且编造性能数据的供应商),这块就不再此处详述了,这完全和公司的环境和体制有关。
总之,第一步就是定规矩!
关于运维能力薄弱这点,我这人不习惯依靠别人,所以性能环境被我完全接了过来,运维给我平台的虚机分配的权限,剩下的完全由我自理!
第二步,抓环境!(性能测试必须对性能环境有100%干预能力!)
关于第2点,组内成员性能能力的问题,只能靠我多次的培训去提升他们的性能水平和意识了。我也从性能初级逐步走过来的,所以针对初级性能或者是仅仅停留在根据简单使用的基础上的组员,进行了快速高效的指导(在项目中成长!)
所以第三歩,就是循序渐进的促组员!(包括问题的分析思路、定位案例等等,实时给他们讲解……费了我一个月的时间)
---------------------以下就是平台建设的过程和思路【干货】--------------------------------
初级和资深的性能测试差别在什么地方?
就是针对各项资源的敏感度认知!比如基本的资源监控、Jvm监控、DB的监控,如果是初级性能,这对对他们而言十分困难,所以最快的方法,就是先认图,在学原理!
那么监控的重要性就出来了!有监控,可以先让他们先意识到问题!
1、监控分为硬件监控和应用监控。
监控工具主要是Grafana+telegraf+influxDB(尽可能用的一个平台满足大部分的监控需求)
值得一提的是:所有的监控报表,我亲自做过定制,去除冗余的,留下重要要的。(制作模板的人,对性能监控项也不太清楚,太多没有用的监控只会给小白造成干扰;有用的报表却没添加上去。)
![0037d45300256d2dcf189d7d20cd408d.png](https://i-blog.csdnimg.cn/blog_migrate/a010dd2bf2d6d5da433c7c42d1836e08.jpeg)
A、硬件监控就是最基础的cpu、内存、IO之类,如下图
Linux资源监控
![4a14032138d3e7fb790c493ae2f68a4f.png](https://i-blog.csdnimg.cn/blog_migrate/0071afe236ffa4e25ccc68a174e7659f.jpeg)
Window资源监控
![ba2dadde7ad554251be1b6d936adc1d0.png](https://i-blog.csdnimg.cn/blog_migrate/ede1a4418dd3e5d2e8efa80cbfd87993.jpeg)
B、应用监控,分为两种,一种是全链路级监控,一种是应用自身资源监控
Java服务的全链路级监控:pinpoint
可以让测试人员查看到具体的接口情况,是调优必备的利器
![dfeaebf5a9936342668e7f101cc4e6b4.png](https://i-blog.csdnimg.cn/blog_migrate/f07ed75b181cf3f17530318041c367a8.jpeg)
可以看到具体的耗时所在,及接口请求(包括慢的sql也可以瞬间抓出)
![229dcaf27b1a9e228319e0968a140ae3.png](https://i-blog.csdnimg.cn/blog_migrate/fe81c9110efc7dfedf9184386c70e358.jpeg)
应用的自身的资源监控,就比较多了,我随便贴几张报表吧
下图的都是telegraf支持的!
![191c39123a7dc426f208f13944371a51.png](https://i-blog.csdnimg.cn/blog_migrate/24ace173795c1cdcd375bd6d3f37061b.jpeg)
如:mongoDB监控
![c309fea3f73cfc451cf08587c5717b88.png](https://i-blog.csdnimg.cn/blog_migrate/76d6684b5951bfc9b7324783e73aff43.jpeg)
Redis监控
![fe56129b232b776c75adc10139cbb1f1.png](https://i-blog.csdnimg.cn/blog_migrate/8fce2391f253002533226000c2215341.jpeg)
mysql监控
![91ead9970d446298a10658fa9f744dec.png](https://i-blog.csdnimg.cn/blog_migrate/d36b5643376c1da9b346afe00d8a9d6e.jpeg)
甚至,包括.net IIS 监控
![05e73348a076ef082a3e1fbfdbf7e582.png](https://i-blog.csdnimg.cn/blog_migrate/8763bcd4eb818146e0b14e5c76465d91.jpeg)
有了监控利器,才能在第一时间去发现问题,进一步的定位问题!
举个例子,你让新人去了解Linux top 的各个参数是什么,load是什么,肯定没有告诉他图表在呈现什么时候的曲线时,就意味的出问题了,简单很多!
附上telegraf的配置:
mysql
# # Read metrics from one or many mysql servers
[[inputs.mysql]]
# ## specify servers via a url matching:
# ## [username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify|custom]]
# ## see https://github.com/go-sql-driver/mysql#dsn-data-source-name
# ## e.g.
# ## servers = ["user:passwd@tcp(127.0.0.1:3306)/?tls=false"]
# ## servers = ["user@tcp(127.0.0.1:3306)/?tls=false"]
# #
# ## If no servers are specified, then localhost is used as the host.
# servers = ["tcp(127.0.0.1:3306)/"]
servers = ["root:ROOT@tcp(localhost:3306)/?tls=false"]
MongoDB
# Read metrics from one or many MongoDB servers
[[inputs.mongodb]]
## An array of URLs of the form:
## "mongodb://" [user ":" pass "@"] host [ ":" port]
## For example:
## mongodb://user:auth_key@10.10.3.30:27017,
## mongodb://10.10.3.33:18832,
servers = ["mongodb://127.0.0.1:27017"]
Redis
[[inputs.redis]]
# ## specify servers via a url matching:
# ## [protocol://][:password]@address[:port]
# ## e.g.
# ## tcp://localhost:6379
# ## tcp://:password@192.168.99.100
# ## unix:///var/run/redis.sock
# ##
# ## If no servers are specified, then localhost is used as the host.
# ## If no port is specified, 6379 is used
# servers = ["tcp://localhost:6379"]
servers = ["tcp://:123456@localhost:8888"]
SQLServer
[[inputs.sqlserver]]
## Specify instances to monitor with a list of connection strings.
## All connection parameters are optional.
## By default, the host is localhost, listening on default port, TCP 1433.
## for Windows, the user is the currently running AD user (SSO).
## See https://github.com/denisenkom/go-mssqldb for detailed connection
## parameters.
# servers = [
# "Server=192.168.1.10;Port=1433;User Id=<user>;Password=<pw>;app name=telegraf;log=1;",
# ]
servers = [
"Server=10.0.088;Port=1433;User Id=sa;Password=YS8D8;app name=telegraf;log=1;",
]
ASPnet IIS
[[inputs.win_perf_counters]] [[inputs.win_perf_counters.object]] # HTTP Service request queues in the Kernel before being handed over to User Mode. ObjectName = "HTTP Service Request Queues" Instances = ["*"] Counters = ["CurrentQueueSize","RejectedRequests"] Measurement = "win_http_queues" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*). [[inputs.win_perf_counters.object]] # IIS, http://ASP.NET Applications ObjectName = "http://ASP.NET Applications" Counters = ["Cache Total Entries","Cache Total Hit Ratio","Cache Total Turnover Rate","Output Cache Entries","Output Cache Hits","Output Cache Hit Ratio","Output Cache Turnover Rate","Compilations Total","Errors Total/Sec","Pipeline Instance Count","Requests Executing","Requests in Application Queue","Requests/Sec"] Instances = ["*"] Measurement = "win_aspnet_app" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*). [[inputs.win_perf_counters.object]] # IIS, http://ASP.NET ObjectName = "http://ASP.NET" Counters = ["Application Restarts","Request Wait Time","Requests Current","Requests Queued","Requests Rejected"] Instances = ["*"] Measurement = "win_aspnet" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*). [[inputs.win_perf_counters.object]] # IIS, Web Service ObjectName = "Web Service" Counters = ["Get Requests/sec","Post Requests/sec","Connection Attempts/sec","Current Connections","ISAPI Extension Requests/sec"] Instances = ["*"] Measurement = "win_websvc" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*). [[inputs.win_perf_counters.object]] # Web Service Cache / IIS ObjectName = "Web Service Cache" Counters = ["URI Cache Hits %","Kernel: URI Cache Hits %","File Cache Hits %"] Instances = ["*"] Measurement = "win_websvc_cache" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
.NET Monitoring
[[inputs.win_perf_counters]] [[inputs.win_perf_counters.object]] # .NET CLR Exceptions, in this case for IIS only ObjectName = ".NET CLR Exceptions" Counters = ["# of Exceps Thrown / sec"] Instances = ["*"] Measurement = "win_dotnet_exceptions" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*). [[inputs.win_perf_counters.object]] # .NET CLR Jit, in this case for IIS only ObjectName = ".NET CLR Jit" Counters = ["% Time in Jit","IL Bytes Jitted / sec"] Instances = ["*"] Measurement = "win_dotnet_jit" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
[[inputs.win_perf_counters.object]] # .NET CLR Loading, in this case for IIS only ObjectName = ".NET CLR Loading" Counters = ["% Time Loading"] Instances = ["*"] Measurement = "win_dotnet_loading" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
[[inputs.win_perf_counters.object]] # .NET CLR LocksAndThreads, in this case for IIS only ObjectName = ".NET CLR LocksAndThreads" Counters = ["# of current logical Threads","# of current physical Threads","# of current recognized threads","# of total recognized threads","Queue Length / sec","Total # of Contentions","Current Queue Length"] Instances = ["*"] Measurement = "win_dotnet_locks" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
[[inputs.win_perf_counters.object]] # .NET CLR Memory, in this case for IIS only ObjectName = ".NET CLR Memory" Counters = ["% Time in GC","# Bytes in all Heaps","# Gen 0 Collections","# Gen 1 Collections","# Gen 2 Collections","# Induced GC","Allocated Bytes/sec","Finalization Survivors","Gen 0 heap size","Gen 1 heap size","Gen 2 heap size","Large Object Heap size","# of Pinned Objects"] Instances = ["*"] Measurement = "win_dotnet_mem" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
[[inputs.win_perf_counters.object]] # .NET CLR Security, in this case for IIS only ObjectName = ".NET CLR Security" Counters = ["% Time in RT checks","Stack Walk Depth","Total Runtime Checks"] Instances = ["*"] Measurement = "win_dotnet_security" #IncludeTotal=false #Set to true to include _Total instance when querying for all (*).
---------
2、平台的建设:
![937107b0eab526397fbd9f21f8d9970b.png](https://i-blog.csdnimg.cn/blog_migrate/71f3c8092f32a08fabbdd8ae4687d885.jpeg)
我走过很多家公司,鉴于我之前提到的他们更看重压测平台的建设,所以上面的这些针对内部管理的和过程的平台,很多公司都不会看作重点!
但相信我,这些东西就是你的组员每天要做的繁琐的东西,平台化可以极大的提升他们做这些低级工作的效率!
这里的平台涉及隐私和机密,我就不在此介绍了!(和压测平台不一样,什么的平台研发而言,比较简单,用开源的框架搞搞,可能一两周就是一个模块。)
需要提醒各位的是,你们到项目过程中需要什么元素字段,一定要提前设计好,想清楚!
而平台化后的过程数据,更便于后面的管理!
3、过程度量报表的出现!
有了上面平台的数据,作为组长,上面的领导问及你们需求情况或者是季度考核时,你再也不用去做重复、繁琐、低效的手动统计了!
![2bbb90b9f4825756080577949f24f0bd.png](https://i-blog.csdnimg.cn/blog_migrate/dda719fbce10f2a87644b10ab485b793.jpeg)
原理如下:我自己写的JOB做数据聚合(实时性要求不高,一个小时执行一次),当然还是依赖强大的grafana!
![aac686d32a22cc02c40287178ada2401.png](https://i-blog.csdnimg.cn/blog_migrate/cf851846bd96f8432fa4e11274fa0353.jpeg)
性能需求和性能问题大盘--便于开发或上级领导,查看实时进展和结果
![de992de189a60995623086e2a214679f.png](https://i-blog.csdnimg.cn/blog_migrate/ed659059f56fc66058e0791e6f3ef12e.jpeg)
人员维度统计--便于考核和汇报--各种维度,十分灵活
![b04361f7f607b91e2138d55d9ab228bb.png](https://i-blog.csdnimg.cn/blog_migrate/466790983c230dea69c58f3431e05028.jpeg)
--------------------------------------------------------------
Grafana个人定制后的性能专项报表,不会免费公开,见谅!
相关技术详贴,后面有时间了我再更新吧!
(未完,待后续更新………………)
---------------------------PartII 性能测试过程管理平台PTPMP----------------------------
语言:PHP(php是世界上最好的语言~手动滑稽)
基于框架:ThinkPHP3.2.3 https://www.kancloud.cn/manual/thinkphp/1687
说明:鉴于安全和隐私,代码不会公开(其实公开也没意义,因为每个公司的业务场景差别较大,所以还是需要定制化的处理的,这也就是我所说的先摸清楚公司内部的流程和不规范的点-->低效的规范化后-->高效的平台化开发,这样可以少走弯路)
平台目的:所在公司的性能测试需求比较特殊,大小产品线有一二十个,此外还有很多供应商开发并交付的项目系统,所以内部需求和外部需求,在没有性能测试规范之前,一直处于多、杂、乱的状态,当然随着规范的落地和推进解决了以上问题,但从性能组内部来说,传统的方式不够高效,所以才有了平台化的需求。
1.性能测试过程的高效管理;
2.性能测试项目需求的过程跟踪及归档(一切数据平台化的原则);
3.高效的合作(开发+测试+项目经理的过程交互),公开透明的数据(排期优先级和人力投入);
开发时长:三个季度,基本上都是空闲时间做的,一个人完成所有模块的设计+开发+测试+上线加内部全面落地使用+维护(当然分模块的优先级逐步上线,并逐步替代传统的excel或者云盘归档的模式)
上面说了,代码不可能给大伙的,但设计和界面可以分享给各位:
![b4c1e8791731fbd09dc6415d6ea416ff.png](https://i-blog.csdnimg.cn/blog_migrate/f3c855c9b2ca3c79c5ea65b62c16d8b3.jpeg)
Step0的监控大盘其实我上面已经说过了,而且很清楚了;
我们关注就是PTPMP的模块设计:
![27b2de68458c05f64a759608cffa493d.png](https://i-blog.csdnimg.cn/blog_migrate/d0bc1f7288256d4d70fabfb0a58d1339.jpeg)
以下是上线后的成品平台的展示:
P0-需求调研管理
![b5274e7749b26f1b2fea2a79731d3664.png](https://i-blog.csdnimg.cn/blog_migrate/bbbef9277ced4aa142e317ea083b59d6.jpeg)
![31e09a9c4f24a3e13e2348403b87c625.png](https://i-blog.csdnimg.cn/blog_migrate/b10475a2fdfba68a2cf3134698f601fe.jpeg)
![2115cd5fd0f1c4ea546510b2126e9aae.png](https://i-blog.csdnimg.cn/blog_migrate/70f1c83dbc541896275c7af8e6f3dc36.jpeg)
P1-需求过程管理
![9cfbd205f1a72882cc19a554ad75d163.png](https://i-blog.csdnimg.cn/blog_migrate/fbdd3b72225a4257009762a502e3e7a1.jpeg)
(嵌入统计大盘)
![c95cc1280c6b0532ccf3c86dc62a198f.png](https://i-blog.csdnimg.cn/blog_migrate/550a50851c8fae783b0517464f7ead0e.jpeg)
P2-性能问题管理
![f12ab96f3f0ec1b19edba6b49605ae25.png](https://i-blog.csdnimg.cn/blog_migrate/8e506e63839208d1ba68b8d5c1207175.png)
顺便附上我们的性能问题页面元素(详细和规范)
![60b45baded4bfca31c3e07d8688b40cc.png](https://i-blog.csdnimg.cn/blog_migrate/02b7f70edb24ad4ef1c8f6ab5bb4b3b3.jpeg)
同样也是统计大盘
![af5a1e7d193424c4c12372071f24a86a.png](https://i-blog.csdnimg.cn/blog_migrate/14b0d740d41a4d52ca744190bb971843.jpeg)
P3-性能环境管理
![69ce7d0cf493953f1e2a81bd6f4d2c7d.png](https://i-blog.csdnimg.cn/blog_migrate/adee8d64197f33e6ff06b063fda7f217.jpeg)
这里说明下,因为公司的环境管理不给力,所以我们自己维护的性能环境;
此外,这里仅仅是环境信息的管理,和服务器操作(新建服务器)没有打通的,不是我们不支持,是他们的对接能力较差……
P4-过程数据管理
![06e89af530d96acd3999b67ef8c81de1.png](https://i-blog.csdnimg.cn/blog_migrate/1c43f08a6de757f7b54fb29869aa8630.jpeg)
对应的就是性能测试报告的过程数据
![b8daacccd2c8a39c70f2373efa8f7f85.png](https://i-blog.csdnimg.cn/blog_migrate/78a318cd8e2cf015d64239b3c26f8a1b.jpeg)
---------------待更新-----------