响应时延

延迟与响应指标

延迟

延迟(latency)和 响应时间(response time)经常用作同义词,但实际上它们并不一样。响应时间是客户所看到的,除了实际处理请求的时间(服务时间(service time))之外,还包括网络延迟和排队延迟。延迟是某个请求等待处理的持续时长,在此期间它处于 休眠(latent)状态,并等待服务。从客户端来看,延迟就是从发送请求到接收响应的整体耗时,包括:请求的网络耗时,请求在服务端的处理耗时以及响应的网络耗时。吞吐量则是服务在一定的并发下,每秒可以处理的请求数。服务延迟的上升不仅仅体现在用户体验的下降,也有可能会导致请求堆积并最终演变为整个业务系统的雪崩。以下为延迟指标的主要关注点:

  • 基础监控:IO 等待、网络延迟;
  • 业务监控:业务相关指标主要需要关注核心功能的响应时长。比如 Zookeeper 的延迟指标 zk_avg_latency,ElasticSearch 的索引、搜索延迟和慢查询。

与错误指标类似,白盒延迟指标通常仅能代表系统内部延迟,建议为主要功能或接口添加黑盒监控来采集端到端的延迟指标。

中位数

每个灰条表代表一次对服务的请求,其高度表示请求花费了多长时间。大多数请求是相当快的,但偶尔会出现需要更长的时间的异常值。这也许是因为缓慢的请求实质上开销更大,例如它们可能会处理更多的数据。但即使(你认为)所有请求都花费相同时间的情况下,随机的附加延迟也会导致结果变化,例如:上下文切换到后台进程,网络数据包丢失与 TCP 重传,垃圾收集暂停,强制从磁盘读取的页面错误,服务器机架中的震动等。

展示了一个服务100次请求响应时间的均值与百分位数

通常报表都会展示服务的平均响应时间,但平均值并不是一个非常好的指标,因为它不能告诉你有多少用户实际上经历了这个延迟。通常使用百分位点(percentiles)会更好。如果将响应时间列表按最快到最慢排序,那么中位数(median)就在正中间:举个例子,如果你的响应时间中位数是 200 毫秒,这意味着一半请求的返回时间少于 200 毫秒,另一半比这个要长。

如果想知道典型场景下用户需要等待多长时间,那么中位数是一个好的度量标准:一半用户请求的响应时间少于响应时间的中位数,另一半服务时间比中位数长。中位数也被称为第 50 百分位点,有时缩写为 p50。注意中位数是关于单个请求的;如果用户同时发出几个请求(在一个会话过程中,或者由于一个页面中包含了多个资源),则至少一个请求比中位数慢的概率远大于 50%。

百分点位

为了弄清异常值有多糟糕,可以看看更高的百分位点,例如第 95、99 和 99.9 百分位点(缩写为 p95,p99 和 p999)。它们意味着 95%,99%或 99.9%的请求响应时间要比该阈值快,例如:如果第 95 百分位点响应时间是 1.5 秒,则意味着 100 个请求中的 95 个响应时间快于 1.5 秒,而 100 个请求中的 5 个响应时间超过 1.5 秒。

响应时间的高百分位点(也称为尾部延迟(tail latencies))非常重要,因为它们直接影响用户的服务体验。例如亚马逊在描述内部服务的响应时间要求时以 99.9 百分位点为准,即使它只影响一千个请求中的一个。另一方面,优化第 99.99 百分位点(一万个请求中最慢的一个)被认为太昂贵了,不能为亚马逊的目标带来足够好处。减小高百分位点处的响应时间相当困难,因为它很容易受到随机事件的影响,这超出了控制范围,而且效益也很小。

百分位点通常用于服务级别目标(SLO, service level objectives)和服务级别协议(SLA, service level agreements),即定义服务预期性能和可用性的合同 SLA 可能会声明,如果服务响应时间的中位数小于 200 毫秒,且 99.9 百分位点低于 1 秒,则认为服务工作正常(如果响应时间更长,就认为服务不达标)。这些指标为客户设定了期望值,并允许客户在 SLA 未达标的情况下要求退款。

排队延迟(queueing delay)通常占了高百分位点处响应时间的很大一部分。由于服务器只能并行处理少量的事务(如受其 CPU 核数的限制),所以只要有少量缓慢的请求就能阻碍后续请求的处理,这种效应有时被称为 头部阻塞(head-of-line blocking)。即使后续请求在服务器上处理的非常迅速,由于需要等待先前请求完成,客户端最终看到的是缓慢的总体响应时间。因为存在这种效应,测量客户端的响应时间非常重要。

为测试系统的可扩展性而人为产生负载时,产生负载的客户端要独立于响应时间不断发送请求。如果客户端在发送下一个请求之前等待先前的请求完成,这种行为会产生人为排队的效果,使得测试时的队列比现实情况更短,使测量结果产生偏差。

微服务中的百分点位

在多重调用的后端服务里,高百分位数变得特别重要。即使并行调用,最终用户请求仍然需要等待最慢的并行调用完成。如下图所示,只需要一个缓慢的调用就可以使整个最终用户请求变慢。即使只有一小部分后端调用速度较慢,如果最终用户请求需要多个后端调用,则获得较慢调用的机会也会增加,因此较高比例的最终用户请求速度会变慢(效果称为尾部延迟放大)。

如果您想将响应时间百分点添加到您的服务的监视仪表板,则需要持续有效地计算它们。例如,您可能希望在最近 10 分钟内保持请求响应时间的滚动窗口。每一分钟,您都会计算出该窗口中的中值和各种百分数,并将这些度量值绘制在图上。

简单的实现是在时间窗口内保存所有请求的响应时间列表,并且每分钟对列表进行排序。如果对你来说效率太低,那么有一些算法能够以最小的 CPU 和内存成本(如前向衰减,t-digest 或 HdrHistogram)来计算百分位数的近似值。请注意,平均百分比(例如,减少时间分辨率或合并来自多台机器的数据)在数学上没有意义 - 聚合响应时间数据的正确方法是添加直方图。

当一个请求需要多个后端请求时,单个后端慢请求就会拖慢整个终端用户的请求

RT | 响应时间

响应时间即 RT,处理一次请求所需要的平均处理时间。对于 RT,客户端和服务端是大不相同的,因为请求从客户端到服务端,需要经过广域网,所以客户端 RT 往往远大于服务端 RT,同时客户端的 RT 往往决定着用户的真实体验,服务端 RT 往往是评估我们系统好坏的一个关键因素。

假设我们的服务端只有一个线程,那么所有的请求都是串行执行,我们可以很简单的算出系统的 QPS,也就是:QPS = 1000ms/RT。假设一个 RT 过程中 CPU 计算的时间为 49ms,CPU Wait Time 为 200ms,那么 QPS 就为 1000/49+200 = 4.01。CPU Time 就是一次请求中,实际用到计算资源。CPU Time 的消耗是全流程的,涉及到请求到应用服务器,再从应用服务器返回的全过程。实际上这取决于你的计算的复杂度。

CPU Wait Time 是一次请求过程中对于 IO 的操作,CPU 这段时间可以理解为空闲的,那么此时要尽量利用这些空闲时间,也就是增加线程数。CPU 利用率是业务系统利用到 CPU 的比率,因为往往一个系统上会有一些其他的线程,这些线程会和 CPU 竞争计算资源,那么此时留给业务的计算资源比例就会下降,典型的像,GC 线程的 GC 过程、锁的竞争过程都是消耗 CPU 的过程。甚至一些 IO 的瓶颈,也会导致 CPU 利用率下降(CPU 都在 Wait IO,利用率当然不高)。

用户平均请求等待时间(Time per request)计算公式:处理完成所有请求数所花费的时间/(总请求数 / 并发用户数),即 Time per request = Time taken for tests /(Complete requests / Concurrency Level)

服务器平均请求等待时间(Time per request: across all concurrent requests),计算公式:处理完成所有请求数所花费的时间 / 总请求数,即 Time taken for / testsComplete requests 可以看到,它是吞吐率的倒数。同时,它也等于用户平均请求等待时间/并发用户数,即 Time per request / Concurrency Level

上一页
下一页