笔者从事某副省级市政务云系统运维7年,最近被下面这张图吸引开始阅读Brendan Gregg的《性能之巅 第二版》,下面将结合自己的运维经验一起来看看这本700多页的书。
系统性能的影响因素涉及软件和硬件,CPU、内存、磁盘io、网络设备、操作系统和应用中间的配置、数据库等等,涉及很多很多的组件,而用户使用过程中往往只会抛出一个很模糊的问题:系统卡顿,网页加载不出来。这种问题往往比系统直接报错打不开更难排查。
在私有云环境中,平台硬件和上层软件应用往往是不同的厂商负责运维,两者之间存在沟通问题,当问题出现时,软件厂商可能看到磁盘io延时高,CPU内存使用率升高,就把问题甩给硬件性能,要求提升硬件配置。而云平台运维厂商又觉得是软件BUG,数据库语句写得拉跨导致。从而形成了互相甩锅的局面,但甩锅并不能解决问题,有效的沟通才可以。
因此当系统出现性能问题时,软硬件厂商尽快建立沟通,梳理出各个组件之间的关系和业务数据路径,并依次排查数据路径上的各个节点。
系统性能的典型目标是通过减少延时和降低计算成本来改善用户体验。系统性能的优化都是建立在一定的成本之上的,因为所有的性能问题都可以通过不计成本的扩容来解决,但这并不现实,所以如何优化系统让其合理地充分利用有限的资源来提供低延时的用户体验才是研究重点。
全栈:从应用程序到硬件的整个软件栈,包括系统库、内核和硬件本身。
上图是第一版的通用系统软件栈示意图,在第二版在用户级中加了一个编译器。
系统性能是一项需要多类人员参与的事务,包括系统管理员、网站可靠性工程师、应用开发者、网工、dba等等。而在实际工作中,一个工程师往往要身兼数则,比如系统管理员大多需要掌握网络、数据库等运维技能。
本章介绍了软件项目生命周期中从构思到开发再到生产部署的理想步骤。
1、设置性能目标和建立性能模型
2、基于软硬件原型进行性能特征归纳
3、在测试环境中对正在开发的产品进行性能分析
4、非回归性测试
5、基准测试
6、生产环境中的概念验证测试
7、生产环境性能调优
8、监测生产环境软件
9、性能问题分析
10、事件回顾
11、开发性能工具
作为系统工程师对软件开发过程简单了解即可。
容量规划:在设计阶段,通过研究开发软件的资源占用情况,来得知原有设计在多大程度上能满足目标需求。部署后,包括监测资源的使用情况,这样问题在出现之前就能被预测。 结合政务云资源申请情况,各个单位在申请云资源时,需要提供申请所需规格资源的依据,软件厂商为保障系统不会卡顿,在方案设计时往往会尽量往高了要;后来大数据局引入了监理单位对资源申请进行审核,这就需要软件开发厂商在申请之前就要做好容量规划,评估软件上线后的业务压力和并发量提前进行模拟压力测试。而往往软件厂商并没有这种能力,所以在实际申请时,监理大多都按2核4G的最小配置审批,业务上线后再根据实际使用情况进行扩容。
像前文提到的,在遇到性能问题时,软件工程师习惯应用程序-系统调用-内核-设备这种自上而下的负载分析视角,而系统管理员则是相反地自下而上的进行资源分析。
指标数据是客观的,比如IO平均响应时间100ms,只要监测软件正常,它就是实际存在的。但100ms的IO延时在没有具体业务场景的情况下不能说是好是坏。然而性能却是一个比较主观的概念,比如我打开一个单位官网用了1s觉得可以接受,但玩FPS游戏如果1s的延时就不用玩了。
所以要将主观的性能客观化,就需要对指标数据设置一个范围或定义清晰的目标,在范围内的指标是可接受的。当然这个范围或目标只是一个参考,而且针对不同的业务需求也有差异。
连锁故障:出故障的组件会导致其他组件产生性能问题,必须理清组件之间的关系,了解他们怎样协调工作的。有时候修复了一个问题可能把瓶颈推向系统其他的部分,举个栗子,疫情开始时,紧急要上口罩预约系统,之前政务云上从没有过秒杀类业务的经验,导致第一天开抢后,软件负载均衡SLB被压垮,业务访问在第一道门就被拦住了,后端应用服务器都没多少业务流量。之后我们又紧急上了硬件负载,第二天负载均衡扛住了,但突发的大访问量又导致单节点的mysql数据库崩溃。
一个性能问题可能隐含了多个原因,在低业务压力的场景下相安无事,但随着业务压力的增加会一起暴露出来。
量化性能的指标:延时
延时测量的是用于等待的时间,所有操作完成的耗时。举个例子,延时可以表示从点击链接到屏幕显示整个网页加载完成的时间。
我觉得延时本质上就是高速设备等待低速设备完成请求的时间,比如CPU向内存取值,需要等来内存寻址,映射、甚至再从磁盘取值的时间。而计算机设备中最慢的组件就是磁盘,所以实际生产中遇到的大部分性能问题最后都会归咎于低速的磁盘io。
性能指标的采集、监控和分析。
应用程序和内核通常提供关于其状态和活动的数据:操作计数、字节计数、延时测量、资源使用率和错误率。计数器在软件中是被硬编码的,其中一些是累积递增的,性能工具可以在不同的时间读取这些累积的计数器,从而计算统计数据,比如平均值、百分比等。
比如linux的vmstat 从/proc中获取内核计数器,再根据数据进行统计和汇总。
计数器到报警的层次结构:
计数器 -> 统计数据 -> 指标 -> 报警
/proc vmstat Grafana prometheus
一种不断提炼汇总的流程,类似ETL的逻辑。
这里介绍一个vcenter中比较直观体现虚机性能的监控指标:CPU就绪时间,指的是 在上次测量时间间隔内,虚拟机已准备就绪,但无法调度以在物理CPU上运行所用的时间。简单来说就是体现了虚机在宿主机上占用物理CPU的效率,就绪时间越长,CPU等待时间越久,此时CPU主频使用率反而比较低,常常出现在宿主机上创建了过多虚机的情况下。
使用工具进行采样,取一个测量子集,来描绘目标的粗略情况。
CPU火焰图:对CPU上的代码路径进行时间间隔的采样。第六章会进行详细解释;
前面两种属于针对历史累积的数据进行分析,跟踪则是实时捕获当前事件,比如tcpdump和strace,还有通用的工具:Ftrace、BCC、bpftrace。
静态检测:添加到源代码中的硬编码的软件检测点。
execsnoop-专门用于为追踪短时进程(瞬时进程)设计的工具;
它通过 ftrace 实时监控进程的 exec() 行为,并输出短时进程的基本信息,包括进程 PID、父进程 PID、命令行参数以及执行的结果。
github地址: https://github.com/brendangregg/perf-tools/blob/master/execsnoop
如何安装使用:将上面的github的内容复制,然后写入execsnoop文件,并且加上x权限即可;
动态检测:在软件运行起来后,通过修改内存指令插入检测程序来创建检测点。类似于调试器在软件的任何函数上插入断点。
BPF:
简单解释BPF作用,BPF提供了一种当内核或应用特定事件发生时候,执行一段代码的能力。BPF 采用了虚拟机指令规范,所以也可以看一种虚拟机实现,使我们可以在不修改内核源码和重新编译的情况下,提供一种扩展内核的能力的方法。
BPF程序不像一般程序可以独立运行,它是被动运行的,需要事件触发才能运行,有点类似js里面的监听,监听到按钮点击执行一小段代码。这些事件包括系统调用,内核跟踪,内核函数,用户函数,网络事件等。
具体能干嘛那,作用还是很强大,可以进行系统故障诊断,因为其有透视内核的能力;网络性能优化,因为它可以在内核态接收网络包,并做修改和转发;系统安全,因为它可以中断非法连接等;性能监控,因为其透视能力,可以查看函数耗费时间从而我们可以知道问题到底出在哪里。
对系统施加合成的工作负载的同时测量系统的性能。类似压测和上线前检测。在生产环境系统上,应该先尝试观测工具。
云计算带来了一些租户性能隔离等新问题。
作者提供了一个基于Linux工具的检查表,可以在调查性能问题的头60s执行,使用的大部分是比较基础的传统工具。
1. uptime
2. dmesg | tail
3. vmstat 1
4. mpstat -P ALL 1
5. pidstat 1
6. iostat -xz 1
7. free -m
8. sar -n DEV 1
9. sar -n TCP,ETCP 1
10. top
具体执行可参考:60 秒 Linux 检查清单,快速初步定位你的性能问题-腾讯云开发者社区-腾讯云
作者给了两个虚构的示例,一个是与磁盘IO相关的性能问题,一个是对软件新版本的性能测试。问题定位过程都比较经典,感兴趣的朋友多的话,我单独开篇文件讲讲。