在线服务需要哪些监控

在生产环境下,我们需要了解在线服务当前运行的状态,而实时监控就是一个这样的工具,有了实时监控,我们就可以时时刻刻了解到,我们的服务当前是不是健康的,有哪些问题。

那么实时监控如何来做呢?我当前所在的公司目前使用的是prometheus + grafana的方式,这也是业界很常用的一种方式。使用prometheus来采集监控指标,grafana生成图表。 至于prometheus + grafana具体如何使用,不在本篇文章的讨论范围,有时间的话,我会专门写一篇如何使用prometheus + grafana来做实时监控的文章。 在本篇文章中,我们重点讨论,通过哪些指标,我们能够对服务进行360度无死角的监控。我认为,可以分为以下三大块。

一、资源相关监控

资源相关监控指的是,在线服务所使用的服务器资源相关的监控。常用的指标有:

服务的实例个数

实例个数,这可以说是分布式服务的一个最基本的指标了。通过实例个数,我们能判断我们服务当前所耗费的资源。这里还要再细化为, 正在运行的实例个数和正在重启的实例个数。对正在重启的实例个数加上实时监控,是很有必要的,服务无法正常启动,一定是出现了很严重的bug,需要我们马上处理。

CPU负载

对于在线服务来说,流量的大小、CPU的负载、服务接口的响应耗时,这三者一般是线性关系,即流量增大后,CPU负载会升高,接口的响应耗时会上升。 因此集群的CPU负载会作为分布式服务扩容的一个条件,当CPU负载超过某个阈值后,服务就会开始扩容,直到集群的CPU平均负载下降到某一阈值。以此来保证接口响应耗时不会上升。 关注集群的平均CPU负载是没有意义的,因为我们一般都会对服务开启动态扩容,因此平均CPU都是在某个区间进行浮动。所以关注CPU的负载, 往往是在全量上线前的灰度上线过程中,关注灰度实例的CPU负载,如果明显超过其他的老版本实例,那就说明全量上线后,服务的实例个数会超过之前的水平, 也就是说本次上线的功能会增加我们的服务器成本。这时候,对于go实现的服务,一般会通过pprof来进行优化,当然这就不再本次讨论范围之内了。

内存使用率

关注内存使用率与关注CPU负载的道理差不多,都是在我们灰度上线过程中,当灰度实例的内存使用率明显高于其他老版本实例时,需要我们进一步确认问题所在。 对于在线服务来说,内存往往不会是资源瓶颈,除非是在服务内部加载了大量的数据缓存。所以当观察到内存持续上升时,我们第一时间要考虑,是不是有内存泄漏。 如果确认不是内存泄漏,而是由本次功能上线带来的一个正常的影响时,就需要考虑升级容器的配置了,给容器多加点内存。

网络IO

正常情况下,网络IO和流量的大小也是成正比的。在流量不变的情况下,如果观察到IO明显升高,要分析:

  1. input升高,接口的request body是不是增大了?服务内部调用其他服务的response body是不是增大了?
  2. output升高,与input刚好相反。

当然还有其他很多可能的问题,比如是不是从数据库查了大量的数据回来,等等,就不一一分析了。

gc相关

对于Java、golang服务,要加上gc次数、gc耗时的监控。

线程数、协程数

对于Java服务,关注线程数;对于golang服务,关注协程数。

二、接口相关监控

接口相关监控,是指我们对外提供的接口相关的监控,以及我们服务内部请求其他服务接口相关的监控,常用的有:

QPS

监控QPS能够了解到当前流量的大小。对于我们服务对外提供的接口,当QPS有突变时,我们一般需要跟调用方确认,对方调用我们接口这块有没有问题; 对于我们服务内部调用其他服务的接口,监控QPS到有突变时,我们要确认我们调用其他服务的这块逻辑有无问题。

流量同比

设置一个窗口期(如10分钟)内的流量数量与昨日或前三日、前五日的一个比值监控,能够让我们了解到当前的流量水平是不是正常的,如果观察到有突变, 我们需要马上找接口调用方确认有无问题。

接口失败率

这是一个很关键的指标,当观测到接口失败率 > 0时,就需要马上确认问题所在。只关注集群的接口平均失败率,其实不太好定位具体哪个实例有失败。 因此往往还要再设置一个单实例级别的接口失败个数,这样就能直接定位到具体某个实例,通过查询error日志,来定位问题。一般接口失败率这个监控, 报警级别都要设置为最高,即需要马上处理。

耗时分位图

这也是一个很关键的指标,接口耗时可以表现出我们接口的性能。这里我们要使用分位图而不是平均值来表示耗时,这是因为平均值无法体现出长尾请求, 而分位图则可以。大部分情况下,我们对服务代码进行优化时,一个很关键的指标就是99分位耗时下降多少。

http响应码的比例

对于http的接口,我们还要关注响应码的比例,200占多少,4xx、5xx,这种失败请求占多少。当然这个指标一般都是在网关采集的,我们服务内部一般不会进行打点。

限流次数

当流量瞬间猛增,我们的集群还没来得及扩容时,此时需要限流,否则服务会被大流量打挂掉。限流次数也需要关注下。

接口降级率

这个指标特指的是,我们服务内部调用其他服务接口时的降级率。降级一般是由于请求的接口响应时间过长,或是出错导致的。当降级率过高时, 我们需要找接口提供方确认,对方的服务有无问题。

接口熔断次数

一个跟接口降级率类似的指标。熔断是指当降级率持续一段时间超过阈值时,就不再请求这个有问题的接口了,直接走降级的业务逻辑。出现熔断时, 往往标志着对方的服务已经有问题了。

三、业务相关监控

业务监控与上面提到的两种监控都不同,它往往没有固定的指标,需要我们对我们这项业务、这个功能,设置定制化的监控指标。我们的业务功能关注什么, 我们就需要对这个关注点做监控。这里我列出两个样例:

流量作弊的比例

我们affiliate反作弊服务,首要关注的业务肯定是affiliate流量作弊的比例。因此对该服务需要设置流量作弊比例的指标,以及更加细化的作弊原因的指标。 这样我们能实时了解到当前流量的质量。

广告召回个数

我们广告系统对外提供接口,客户端来拉取广告。有个很关键的指标我们需要关注:每次请求召回了多少条广告。更细化的,我们可以分APP、分广告位的来看这个指标。

四、最后谈谈关于报表和监控

有人会说,实时监控只需要最基础的一些资源监控和接口监控就行了,业务相关的指标我可以看报表啊,报表可观测的维度可比实时监控要多很多。 这确实是实话,我们通过报表可以设置十几个维度来观测数据,这是实时监控无法做到的。但相比于报表,实时监控的优势其实也很明显:

  1. 查询速度。报表存储的是每一条记录,因此查询一次报表数据,需要做数据聚合,少则几秒,多则几十秒;而实时监控存储的实际上是聚合信息,它的查询速度要快很多, 基本是毫秒级别,因此我们一般都会把实时监控看板设置为自动刷新。
  2. 数据的展现。实时监控的指标数据存储一般都是存储为时序数据,因此可以生成很平滑的指标曲线;而报表进行数据展现时,一般都是固定天或小时的数据, 因此无法做到平滑的展示数据,举个例子,看一天的数据,实时监控可以每分钟生成一个数据点;而报表则只能每小时生成一个数据点。在这个基础上, 报表是无法做到滑动窗口内的数据昨日同比的,因为报表聚合出来数据粒度太粗了。