性能问题通常是复杂而神秘的,并且可能提供很少或根本没有关于其起源的线索。在没有起点或提供方法的情况下,通常会随机分析性能问题:猜测问题可能出在哪里,然后进行更改直到问题消失。虽然如果我们猜对了这可能会很有成效,但它也可能非常耗时或具有破坏??性,并且最终可能会忽略一些问题。系统性能问题由于典型系统中的组件数量众多,因此系统性能分析非常复杂。环境可以包括数据库、Web服务器、负载平衡器和自定义应用程序等,所有这些都在操作系统(裸机或虚拟)上运行。那只是软件;硬件和固件(包括外部存储系统和网络基础设施)为环境添加了更多组件,其中任何一个都是潜在的问题根源。每个组件可能需要自己的专业领域,公司通常没有了解其环境中所有组件的员工。性能问题也可能源于独立运行良好的组件之间的复杂交互,解决此类问题可能需要多个领域专家的共同努力。另一个复杂的因素是性能的好坏可能是主观的:一个用户不能接受的延迟可能对另一个用户来说是可以接受的。如果没有办法清楚地识别问题,不仅很难知道问题是否存在,而且也很难知道问题何时得到解决。衡量性能问题的能力需要能够量化这些问题并按重要性对不同问题进行排序。性能分析方法可以提供一种有效的方法来分析系统或组件并确定问题的根本原因,而无需深入的专业知识。方法论还可以提供识别和量化问题的方法,以便可以理解和排序问题。具体绩效清单已成为一种流行的资源。但是,可观察性仅限于列表中的特定项目,这些项目通常已经过时并且需要更新。这些清单可能侧重于可以轻松记录的已知问题,例如可调设置,但不包括源代码或环境的自定义补丁。既然如此,就出现了关于性能问题的普遍现象。关于系统性能的反方法论的第一个现象是“甩锅”,一种常见的方式:找到一个你不负责的系统或环境组件。假设问题出在那个组件上。将问题转给负责的团队。如果证明错误,则返回第一步。例如,“可能是网络问题。你能和网络团队核实一下,看看他们是否丢包之类的吗?”这种方法不是调查性能问题,而是将它们变成别人的问题,这很可能会浪费其他团队的资源。缺乏数据分析,即使是一开始,也导致了这种假设。第二种方式是运行工具和收集数据,这比随意假设要好,但仍然不足以进行有效的性能分析,这是缺乏周到的方法。用户通过选择他们熟悉的、在互联网上找到的或随机找到的可观察性工具来分析性能,并查看是否出现任何迹象。这种即兴的方法可能会忽略许多类型的问题。找到合适的工具需要一段时间,最熟悉的工具会先运行,即使它们不是最有意义的。学习更多工具会有所帮助,但仍然是一种有限的方法。由于缺乏可观察性工具或指标,某些系统组件或资源可能会被忽略。此外,我们可能没有意识到视图是不完整的,没有办法识别“未知的未知数”。现有的性能分析方法可以使用更好的能够在运行工具之前解决问题的性能分析方法,包括问题陈述法、负载整形法和演练分析法。问题陈述法问题陈述法常被客户服务或支持人员用来收集问题信息,可用于性能分析。其目的是收集问题的详细描述以指导更深入的分析,而这种描述甚至可能解决问题本身。这通常通过询问以下问题进入分析:什么会被视为性能问题?这个系统曾经运作良好吗?系统最近发生了什么变化?(软件?硬件?负载?)性能下降可以用延迟或执行时间来解释吗?指示?该问题是否影响其他人或应用程序(或仅影响您自己)?什么是环境?您使用的是什么软件和硬件?版本?配置?这些问题可以针对特定场景进行定制。这样的问题看起来很明显,答案往往可以解决一类问题,而不需要更深入的方法。如果不是这种情况,可以调用其他方法提供服务,包括负载整形和演练分析。负载整形方法可以是属性,例如:谁在引起负载?进程ID、用户ID、远程IP地址?为什么会产生异常负载?可能的代码路径?负载的其他特性是什么?类型?负载如何随时间变化?这些问题有助于将负载问题与架构问题区分开来。最佳性能通常来自消除不必要的工作。有时,这些瓶颈是由应用程序故障引起的(例如,线程陷入循环),或者它们可能是由错误配置引起的。这种不必要的工作可以通过维护或重新配置来消除,负载整形可以识别这种变化问题。向下钻取分析向下钻取分析包括剥离软件和硬件层以找到问题的核心,向下钻取到不同的细节级别。这些更深入的细节甚至包括检查内核的内部结构,例如,通过对内核堆栈跟踪进行采样,或通过动态跟踪检查内核函数的执行。钻取分析包括:监控,随着时间的推移持续记录许多系统的高级统计数据,并在出现问题时识别或发出警报。识别,如果怀疑系统有问题,这将使用系统工具将调查范围缩小到特定资源或感兴趣的区域,并识别可能的瓶颈。分析,进一步检查特定系统区域以确定根本原因并量化问题。分析阶段可以向下钻取,从软件堆栈顶部的应用程序开始,向下钻取到系统库、系统调用、内核内部结构、设备驱动程序和硬件。虽然向下钻取分析通常可以确定问题的根本原因,但这样做可能很耗时,而且在错误的方向上钻取会浪费大量时间。有没有更有效的方法?尽早快速定位性能问题对于每个资源,我们可以查看其利用率、饱和度和错误。资源是指所有物理服务器功能组件(cpu、磁盘、总线等)单独检查,一些软件资源也可以用同样的方法检查。利用率是资源在特定时间间隔内工作的时间百分比。当繁忙时,资源可能仍然能够接受更多的负载,这取决于饱和度。对于某些资源类型,例如内存,利用率是所使用资源的容量,这与基于时间的定义不同。一旦容量资源达到100%利用率,要么对负载进行排队(饱和),要么返回错误。错误是指当故障模式可恢复时可能不会立即注意到的错误事件的数量。这包括失败和重试的操作,以及冗余设备池中的失败设备。尝试迭代系统资源而不是从工具开始,创建一个完整的问题列表,然后只搜索能够回答这些问题的工具。即使回答这些问题的工具非常有用,它们现在也只是“已知的未知数”。尽量指向有限的几个关键指标,以最快的速度检查所有系统资源。在此之后,如果没有发现问题,您可以继续使用其他方法。指标指标包括:利用率:一段时间内的百分比(例如,CPU的利用率为90%)。Saturation:等待队列长度(例如CPU的平均运行队列长度为4)。错误报告中的错误数量(例如,最近50次网络交互的冲突)。指示测量值的时间间隔也很重要。虽然这似乎有悖常理,但短期的高利用率可能会导致性能问题,即使在较长时间间隔内总体利用率较低也是如此。例如,CPU利用率在第二个尺度上可能变化很大,五分钟内的平均利用率可以掩盖100%的短暂饱和度问题。资源列表需要完整的资源列表才能快速定位性能问题。例如,服务器硬件资源的一般列表如下:CPUーsockets,cores,hardwarethreads(virtualcpu)。内存—DRAM网络接口—以太网端口存储—磁盘控制器—存储、网络。每个组件通常是一种资源类型。例如,主内存是容量资源,网络接口是I/O资源,可以用IOPS或吞吐量来衡量。有些组件可以表示不止一种资源类型——例如,存储设备既是I/O资源又是容量资源,所有可能导致性能瓶颈的类型都需要考虑。请注意,I/O资源可以进一步抽象为队列系统,该系统对这些请求进行排队,然后为这些请求提供服务。在高利用率或饱和时造成性能瓶颈的资源是最值得关注的资源,而缓存在高利用率时提高性能。解决系统瓶颈问题后,您可以检查缓存命中率和其他性能属性。如果不确定是否包含资源,请包含它并查看该指标在实践中的工作方式。功能框图遍历资源的一种方法是查找或绘制系统的功能框图。这种图表显示了资源之间的关系,这在发现数据流中的瓶颈时非常有用。在确定各种总线的利用率时,在功能图上用最大带宽标记每条总线。在进行单次测量之前,可以根据功能框图探测系统瓶颈。CPU、内存和I/O的互连性常常被忽视。幸运的是,它们通常不是系统瓶颈的原因。不幸的是,当它们确实出现时,问题可能很难解决,可能需要升级主板或减少负载。指标获得资源列表后,请考虑每种资源所需的指标类型(利用率、饱和度和错误数)。这些指标可以表示为每个时间间隔的平均值或计数。请注意当前不可用的指标:这些“已知的未知数”最终会列出大约几十个指标,其中一些指标很难衡量,而另一些则根本无法衡量。幸运的是,最常见的问题通常会以更简单的指标出现,例如CPU饱和度、内存容量饱和度、网络接口利用率、磁盘利用率等,因此请先检查这些指标。其中一些指标可能无法从操作系统工具中获得,您必须编写自己的软件才能使用DTrace或CPU性能工具获取它们。软件资源类似的检查可用于某些软件资源,通常用于较小的软件组件而不是整个应用程序。例如:互斥锁。利用率可以定义为持有锁的时间,饱和度是等待锁的线程队列。线程池。利用率可以定义为线程忙于处理工作的时间量,饱和度可以定义为等待线程池处理的请求数。进程/线程容量。一个系统可能只有有限数量的进程或线程,它们的当前使用可以定义为利用率;等待分配可能表示饱和;分配失败时会发生错误。文件描述符容量,同上。如果可以适当地衡量它们,就可以使用这些指标;否则,软件故障排除可以留给其他方法。性能定位策略性能问题定位的核心是确定使用哪些指标。从操作系统读取这些指标后,您需要解释这些指标的当前值。对于某些指标,解释可能很明显并且有据可查)。指标,如果不明显,可能取决于工作量需求或对它们的期望。错误首先出现,因为它们通常比利用率和饱和度更容易和更快地解释。不幸的是,一个系统可能会遇到不止一个性能问题,首先执行标准操作、检查资源表并列出发现的任何问题,然后根据可能的优先级调查每个问题会更有效。总结系统性能分析可能很复杂,问题可能来自任何组件,包括它们之间的交互。常见的方法有时类似于猜测、尝试熟悉的工具或在没有确凿证据的情况下做出假设。我们可以实施的一种简单策略是对整个系统执行健康检查。考虑所有资源以避免忽略问题,并使用有限的指标以便可以快速跟进,这对于分布式环境(包括云计算)尤为重要。
