Systems Performance: Enterprise and the Cloud - 1介绍

Introduction

《Systems Performance: Enterprise and the Cloud, Second Edition》

我的博客

Systems Performance

下面给出一个操作系统中,从应用到硬件设备的一个标准的软件栈,编译器也包含在其中,因为编译器对执行性能的影响不可忽视。

Roles

在进行系统性能分析时,有不同的工作分工。有时候性能分析团队只负责单个子系统,比如网络团队负责对网络栈性能分析,数据库团队则负责数据库等。有时候一些性能问题则需要分析性能瓶颈的根因,则需要多个团队协同合作。

Activities

对系统性能的分析涉及不同的阶段:

  • 对未来的产品设置性能目标与性能模型
  • 软件与硬件的性能特性
  • 开发阶段测试环境下的性能分析
  • 新产品版本的非回归测试
  • 新产品发布基准测试
  • 在目标产品环境中进行测试验证
  • 在产品中进行性能调优
  • 对运行中的产品软件进行性能监控
  • 对产品问题进行性能分析
  • 复盘
  • 性能工具开发协助产品分析

Perspectives

抛开其他内容不谈,性能可以从两个视角进行分析,即负载侧与资源侧。资源侧分析视角通常由系统管理者使用,与之对应应用开发者则更倾向于负责从负载端分析性能。

Performance is challenging

Subjectivity

技术往往是客观的,因此工业界的人看待事物总是非黑即白。在软件问题解决的过程中,bug是否存在是否被解决,就是非黑即白的。

性能则不同,它有时候是主观的。同一个产品,它的性能对于这一用户是好的,可以接受的,对另一个用户可能是不好的。这一矛盾可以通过将主观性能设置一个标准来实现,比如要求硬盘的响应时间小于某一值就可接受它是好的产品。

Complexity

性能问题,基于系统复杂度,往往也是复杂的。比如在一个云计算环境中,你甚至不知道首先从哪一个服务器实体进行分析。性能问题也可能由于复杂的子系统之间的交互导致,单独对单个子系统进行分析时,子系统表现的很好,但是一旦合并成为一个整体开始工作时,就会暴露性能问题。性能瓶颈总是以意想不到的方式出现,解决一个性能瓶颈可能并不能按照预期提升整个系统的性能。除了系统导致的性能问题复杂度外,产品负载的复杂特性也会导致复杂的性能问题。

复杂的性能问题,往往需要以整体的方式解决。整个系统,包括其内部交互以及外部交互,都需要分析。这需要较为宽泛的技能。

Multiple causes

一些性能问题并不只由单个根因造成。

Multiple Performance Issues

在复杂软件中,可能不只有一个性能问题,即便在成熟的商业软件中,也可能存在多个尚未被解决的性能问题。

Latency

延迟是一个重要的性能指标。比如下面的数据库访问延迟,如果能够消除硬盘读取时间,那么可以将数据库访问延迟从100ms降低到20ms。

Observability

通过观测来理解系统,观测方法可以分为多种方式,包括计数、分析与跟踪等方式。在产品环境中,尽可能首先尝试观测工具,因为标杆工具修改系统的状态将会造成额外的工作负载,如果测试环境处于空闲状态,那么可以使用标杆工具来确定硬件性能。

Counters, Statistics, and Metrics

应用与内核通常其状态与行为的数据,操作计数、字节计数、延迟测算、资源使用与错误比率等。它们通常以整型变量实现,被称作计数器,这些计数器被放在软件中随软件使用而增长。这些计数值可以使用性能工具查看并做统计。

比如vmstat(8)工具,基于内核/proc文件系统计数值,打印系统级的虚拟内存统计等信息,下面给出打印示例:

$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b 交换 空闲 缓冲 缓存   si   so    bi    bo   in   cs us sy id wa st gu
 0  0   2816 814964 771200 15823144    0    0     9   151 2307    1  1  0 99  0  0  0
 0  0   2816 814712 771200 15823244    0    0     0     0  467  926  0  0 100  0  0  0
 0  0   2816 812980 771204 15822516    0    0     0   132  777 1552  1  0 99  0  0  0
 0  0   2816 816248 771204 15822868    0    0     0     0  768 1115  1  0 99  0  0  0
 0  0   2816 818788 771204 15822472    0    0     0   308  783 1206  1  0 99  0  0  0

度量用来评估或监控一个目标的统计量。大多数企业使用监控代理以固定的间隔记录目标统计项,并将它们汇总到图形用户接口中来查看随时间变化情况。监控软件也可以支持创建定制化的提醒服务,比如当问题出现时发送问题邮件给员工。

Profiling

在系统性能中,性能剖析工具是一类用于测量与分析程序运行时行为的工具,一种常见的可视化分析工具如火焰图。

Tracing

跟踪是对事件的记录,捕获事件数据并将其保存做后续分析或用于后续总结汇报。不同的应用场景下有专用的跟踪工具,比如在Linux环境下,对系统调用的跟踪可以使用strace工具,对网络包的追踪可以使用tcpdump工具。也有通用的跟踪工具,可以分析软件与硬件事件执行,比如Linux系统下的FtraceBCC以及bpftrace工具等。

Static instrumentation

静态指令描述了添加到软件代码中的硬编码软件指令点。比如在Linux内核代码中有成百上千的这样的点,分别位于盘I/O、事件调度与系统调用中。Linux中提供这一功能的点被称作tracepoint跟踪点。在用户态软件中,存在静态技术称作USDT: user statically defined tracing技术。USDT被用在库中,以及一些服务请求中。

比如下面的例子中,使用静态指令execsnoop打印执行指令之后创建的新进程:

# execsnoop
ping             1132422 1132408   0 /usr/bin/ping www.bing.com 

Dynamic instrumentation

动态指令在软件执行过程中,通过修改内存中的信息,插入指令程序的方式创建指令点。这与调试器在正在运行的软件中插入断点的方式类似。这一方法允许用户在运行的软件中进行性能统计。

动态指令与传统的观测方式不同,以操作系统为例,分析内核时,内核内部是一个黑房子,静态点相当于内核工程师在黑房子中放了几根蜡烛,而动态指令则相当于我们自己拥有了一个火把。

动态指令在1994年被创造,一并被创造的还有动态跟踪工具。在2000年Linux中开发了动态指令,并在2004年引入内核(kprobe)。2005年Sun公司开发了它们自己的DTrace。

BPF

BPF: Berkeley Packet Filter,BPF最初作为内核内迷你虚拟机,用来加速tcpdump执行。2013年,其功能做了拓展,变为eBPF成为内核内通用的执行环境,提供安全且快速的资源访问。

Experimentation

除观测工具外,还有实验用工具,这类工具基本都是基准工具。这些工具会为系统制作工作负载并测算其性能。

下面工具使用iperf工具,测试进行TCP网络环境下的呑吐情况:

$ iperf -c 10.80.0.188 -i 1 -t 2
------------------------------------------------------------
Client connecting to 10.80.0.188, TCP port 5001
TCP window size: 16.0 KByte (default)
------------------------------------------------------------
[  1] local 10.80.0.177 port 50496 connected with 10.80.0.188 port 5001 (icwnd/mss/irtt=14/1448/310)
[ ID] Interval       Transfer     Bandwidth
[  1] 0.0000-1.0000 sec  12.1 MBytes   102 Mbits/sec
[  1] 1.0000-2.0000 sec  11.2 MBytes  94.4 Mbits/sec
[  1] 0.0000-2.1086 sec  23.5 MBytes  93.5 Mbits/sec

Cloud computing

云计算方便用户部署自己的虚拟系统运行实例,有些云实例可能生存仅需几分钟或几小时。由云计算与虚拟化使用情景,需要对云环境承租人使用虚拟化环境进行性能管理,比如如果系统没能合理管理,一个用户用尽了盘I/O资源,另一个用户在使用时就会格外煎熬。

Methodologies

有了世界观,需要有方法论支撑我们进行工作,如果做事没有方法论,随机执行动作期望着成功,这无疑是在痴人说梦。

Linux perf analysis in 60 seconds

下面给出一个工具列表,在进行性能分析的前60秒,可以使用这些工具进行一些信息收集:

编号 工具 检查项 具体章节
1 uptime 平均负载,确定负增加或减少 6.6.1
2 dmesg -T | tail 内核错误,包括OOM事件 7.5.11
3 vmstat -SM 1 系统级统计,运行队列长度、交换、CPU使用情况 7.5.1
4 mpstat -P ALL 1 CPU均衡,单个CPU忙碌表明着均衡做得不到位 6.6.3
5 pidstat 1 进程CPU使用情况,判断非期望的CPU消耗情况,用户系统CPU事件 6.6.7
6 iostat -sxz 1 盘I/O统计,IOPS以及吞吐情况,平均等待时间,忙率 9.6.1
7 free -m 内存使用情况,包括文件系统缓存 8.6.2
8 sar -n DEV 1 网络设备I/O,包与吞吐量 10.6.6
9 sar -n TCP,ETCP 1 TCP统计 10.6.6
10 top 总览 6.6.6

Case studies

Slow disks

张伟作为一家中型公司的系统管理员,数据库团队向他提请了数据库服务器盘速度缓慢支持函。

张伟首要任务是了解更多情况,收集信息细节来形成详细的问题描述。支持函中提到了盘速度缓慢,但是并没有解释这一问题是否是由数据库本身问题导致,张伟询问了下面几个问题:

  • 当前是否存在数据库性能问题?如何衡量的?
  • 这一问题出现多久了?
  • 数据库最近有做什么修改吗?
  • 为什么怀疑是盘的问题?

数据库团队回答:"我们有一个日志查询请求超过了1000毫秒,平时不会这样缓慢,在过去的一周内,每小时会有几十次这样的问题出现,AcmeMon工具显示盘忙碌"。

这一回应让张伟判断大概率是数据库问题,但在确认之前,需要更多的信息来验证猜想。

AcmeMon是公司服务器的监控系统,提供历史性能数据监控。张伟使用USE方法(第二章介绍),查看资源瓶颈,正如数据库团队汇报的那样,盘使用率偏高,达到80%,而其他资源如CPU、网络使用率则很低。历史数据展示盘使用率在过去的几周稳步提升,而CPU使用率则偏向稳定,AcmeMon并不提供盘的工作情况或错误统计,因此要完成USE方法,张伟必须登入服务器运行一些指令来查看更多信息。

张伟通过/sys检查了盘错误计数,这一数据显示错误为0。随后张伟运行以一秒间隔运行了iostat查看情况,这一工具显示在一秒的间隔下,盘使用率有时会飙升到100%,增加了盘响应延迟。

随后,张伟使用BCC/BPF跟踪工具,调用offcputime来捕获栈跟踪信息,查看内核在调度离开数据库时的栈信息,并查看CPU不执行数据库软件的时间。栈信息显示数据库总是在进行请求进行文件系统读操作时,进入阻塞状态,这一信息足以让张伟作出判断。

下面要排查为什么会这样了,盘性能统计显示了高负载,张伟使用iostat工具测量IOPS、吞吐能力、平均盘延迟以及读、写速比率等,基于这些信息,张伟更加坚定了自己的判断。

张伟按照自己收集的信息,写了回复函,在回复函中表示盘工作正常,并询问了数据库团队数据库负载是否有增加?

数据库团队回应,数据库负载并未增加,这也与数据收集的一致,因为CPU使用率并没有明显增加。

张伟思考了一下还有哪种情况会导致高盘I/O使用率增加,而不会造成CPU负载增加,同事表示文件系统碎片化可能会造成这样的情况,但是文件系统碎片化通常出现在文件系统100%使用时,而张伟获取到的信息中显示只有30%的使用。

张伟清楚,通过向下钻研透彻整个系统,是能够找到根因的,但是这显然太过于耗费时间了。张伟头脑风暴了可能情况,他想起文件系统缓存(页缓存)未命中可能会导致这一问题。

张伟通过cachestat工具检查了文件系统缓存命中率,查看到当前命中率大约91%,这一数据看起来很高,但是他没有历史数据进行比较。他登陆进入另一个具有相似负载的数据库服务器,查看到另一个缓存服务器的缓存命中率大约在98%。同时他发现,另一台机器上的文件系统缓存内存大小更大。

在收集到内存使用这一信息之后,张伟发现他遗漏了内存情况使用,一个在开发的项目应用正在持续吃掉内存,这一内存本来应该由文件系统缓存使用的,由于命中率降低,导致了文件系统读取由内存读变为了盘读,从而导致了盘I/O率居高不下。

张伟联系了应用开发团队,并请求他们暂时关闭掉应用,帮助定位服务器问题,一切恢复了正常。

posted @ 2025-04-20 22:40  ArvinDu  阅读(32)  评论(0)    收藏  举报