分布式链路追踪技术:如何通过分析数据快速定位系统隐患?

之前的篇章我们了解了统计指标的基本概念。今天我将从用户侧到服务器,监控指标依次有端上访问、应用程序、组件和机器信息,让你更轻松地通过统计数据来了解系统隐患。

端上访问

端上访问一般可以细分为 2 个,App 和网页。 两个虽然都属于端上,但是侧重点不一样,二者之间的区别主要可以是以下 4 点:

  1. 访问方式:这个很好理解,App 需要在应用市场下载使用,下载会花费一定的时间,而网页只需要输入一个地址或直接利用搜索引擎。
  2. 兼容性:从使用者的角度来讲,兼容性十分关键。 App 一般具有很好的兼容性,但由于 Android 厂家相对较多,所以每个厂家可能会有一些细微的差别,但是整体的兼容性不会有太大问题; 网页需要考虑各种不同的浏览器厂商,有些差别还是比较大的,比如最常见的 IE8 相对而言就比较难做兼容。
  3. 内容变更:显示的内容需要变更时,App 往往需要很长的周期,因为需要进行发版、应用审核、上架,最后才到用户更新,所以有时为了方便,在 App 内嵌入 H5 也是很常见的; 网页则是实时的,只需要开发人员将更改后的内容上线,用户访问时就会是最新的。
  4. 使用体验:从用户使用体验角度来讲,App 往往体验更好,因为它是手机上的应用,所以包括在使用、消息推送等方面都有更好的支持; 网页相对来说会差一些,更多的是展示信息的功能,因为它属于在浏览器应用中的内容,所以其权限相对较少。

应用程序

介绍了二者的区别后,我先来讲一讲如今更为用户青睐的 App,看看 App 中有哪些比较常见的指标:

  1. 崩溃率:崩溃指的是应用在运行过程中出现强制关闭的现象。 崩溃会打断了用户操作的体验,造成业务中断。 崩溃率过高还会导致用户的留存率下降,品牌口碑变差,等等。
  2. 卡顿率:App 中的卡顿率指的是 UI 刷新时出现卡顿的情况。 如果卡顿率过高,会让用户感觉 App 运行很慢,降低用户的使用体验。
  3. 卸载率:卸载说明用户很难适应你的产品,卸载率可以算是最能检测用户在使用一个产品时是否满意的一个指标了。 卸载率的升高可能是各个方面导致的,比如推送过多打扰到用户,有严重的 bug 影响到使用体验,等等。

网页

介绍完 App 后,我再带你了解一下网页,网页会更加关注显示体验,所以其中一般会有这样一些指标:

  1. 白屏时间:指的是用户访问页面时,从用户输入地址栏之后到首次出现内容的时间,也叫作首次渲染时间。 白屏时间的长短会影响用户的使用体验,白屏时间长会导致用户认为网站比较慢。 如果出现较长时间的空白,有可能是服务器响应慢或是网络波动等原因造成的。
  2. 首屏时间:指的是用户输入地址栏之后到首个屏幕渲染完成,即完全显示了页面内容的时间。 首屏时间会受资源下载速度影响,首屏渲染的速度越快,用户的使用体验也会更好。

通用指标

端上的资源请求,一般都会经历以下几个步骤:DNS 寻找,建立与服务器的链接,发送请求,请求响应。 这几个步骤是可以被监控起来,现在很多主流的拨测软件也会提供这样的统计功能,拨测软件其实就是利用各个不同地方的机器发起请求,来测试网络情况。

App 和网页,在发送请求和获取数据内容的过程中,除了以上提到的指标,还有以下几个指标需要注意:

  1. DNS 响应时间:通常用来记录访问地址向 DNS 服务器发起请求,到 DNS 返回服务器 IP 地址信息的时间。
  2. 建立连接时间:客户端通过 TCP 与服务器建立的时间。
  3. SSL 握手时间:SSL 握手指的是与 HTTPS 服务器端进行建立链接的整个过程,其耗时就是 SSL 握手时间。
  4. 首字节时间:从客户端发送请求,到接收服务器首个字节的时间。因此,它包含了服务器的响应耗时信息。
  5. 下载内容时间:接收到内容后,内容被完整下载完成的时间。

通用指标并不限于 App 或是网页。通过这些指标,你可以更加了解客户端从请求发起到接收完整内容的耗时情况。通用指标前 3 项(DNS 响应时间、建立连接时间、SSL 握手时间)是基础功能,在优化时更偏向运维层面;首字节时间和下载内容时间,则更多的是后端开发人员来优化。

应用程序

介绍完端上访问后,我们再来看看应用程序。对于应用程序,需要监控的指标就更多了,我会分请求、数据处理、组件协作资源、业务指标、VM 监控这 5 个部分来介绍。

业务指标更多是倾向于开发人员在编写代码时需要自定义控制的指标内容,这一课时我会略过这一内容的介绍,在“07 | 指标编写:如何编写出更加了解系统的指标?”这一课时我会有详细的讲解。

请求

请求指的是端上通过 HTTP 等方式发起的请求,与请求相关的指标有以下几个需要关注:

  1. QPS:我在“04 | 统计指标:‘五个九’对系统稳定的意义?”这个课时中介绍过,QPS 代表了请求数量,它是我们能最快了解这个系统使用情况的一个指标。
  2. 状态码:针对 HTTP(S) 的请求,一般会细化响应状态码的数量指标。2xx:响应被正常处理。一般系统中会使用 JSON 来返回数据,而 JSON 可能会有不同的业务状态码,监控时可以依据具体的情况定制。3xx:请求被重定向。如果出现了大量的重定向,一般就表明该网页存在一定的问题,而且也存在降低用户使用体验的风险。4xx:无法访问,比如我们常见的 403 无权限、404 未找到。4xx 说明业务边界存在问题,可能会导致身份信息出现问题或者页面访问异常。5xx:这个在后端比较常见,如果服务器内部出现了错误,通常也会伴随着访问出现错误。
  3. 请求时间:从服务器发起请求,到服务器返回数据内容的总计时间,一般也叫响应耗时。响应耗时可以帮助我们了解具体某个接口或者页面的执行情况。在“04 课时”中我介绍了直方图和分位值图,通过这 2 种或者是其他的形式展示响应耗时,也更能直观了解耗时的整体分布情况。
  4. SLA:同 QPS 一样,我也在“04 课时”中介绍过。在这里我简单说明一下,在 HTTP 请求层面,SLA 一般可以通过总共的请求数与 5xx 请求数之间的运算获得。
  5. 独立用户数:指的是总共有多少个用户访问。用户数越多,说明产品使用的人数越多,用户基数越大。通过查看独立用户数也可以发现一些问题,比如爬虫在爬取你的数据,就可能会导致 QPS 偏高,而用户数很少的情况。

数据处理

数据处理和一些第三方框架的交互居多,在请求数据处理时,会涉及很多的内容,其中有以下几个比较关键的指标类型:

  1. RPC:你的应用程序一定会有微服务的概念,而且系统之间肯定也会存在 RPC 调用。那么,在调用时就肯定会涉及消费者和提供者。你就可以分别记录消费者和提供者的调用次数、成功率、耗时等信息。 为什么要分别记录?以成功率来说,消费者一般会有超时设置。假设超时设置是 2 秒,提供者第 3 秒才返回数据,它认为自己成功了,但消费者可能早将其认定为超时。所以我们在统计数据时,消费者的成功率是更能提现执行情况的,提供者的数据则更多的是参考。
  2. 熔断限流降级:熔断、限流、降级在高流量的时代也是一个必不可少的内容,比如阿里的 Sentinel,Netflix 的 Hystrix。我们一般都是基于 RPC 或者其他资源的使用情况,来设置相应的阈值进行限流或者熔断的。熔断/限流/降级的次数、阈值,其实也是一个很好的观测指标,我们可以通过这些指标,更清楚地了解阈值是否正确、触发后的处理是否正确,等等。
  3. 数据源:你的系统肯定会涉及各种各样的第三方数据源,比如最经常使用的 MySQL、ElasticSearch、MongoDB。在这里,我们会更加关注与这些系统交互时的执行耗时、调用频次。如果你在和数据库操作时,出现耗时较高的情况,就代表业务逻辑也出现了问题。
  4. 自定义业务指标:以上所介绍的这些固有指标早已不能满足我们对指标的要求,因此我们经常会自定义业务指标,以便能更细化地了解系统。在“07课时”中我会对这部分内容进行讲解。

组件协作资源

我们的应用程序会和各种的第三方框架进行资源利用,对于它们的资源利用的效率,很大程度上决定了应用的执行效率。我将资源分为 5 大类,分别是 RPC、数据库、队列、缓存和请求,再一一介绍每种资源中常见的指标。

  1. RPC:和数据处理中提到的 RPC 类似,组件协作资源中的 RPC 一样会涉及资源利用。以国内使用最多的 Dubbo 为例,Dubbo 的每一次发送请求和接收请求,都是利用线程池完成的。在使用 Dubbo 的时候,你可以通过监控线程池的资源信息掌握系统运行的状态,这其中的指标有总计的线程数活跃线程数等。

我在工作中就遇到过这样的情况:因为一个 Dubbo 接口耗时较长,线程池也没有做到很好的隔离,导致当前服务的资源完全处于等待状态,没有线程可以去处理其他的业务请求,造成了线上的故障。

  1. 数据库:业务系统与数据库之间的交互一般会有专门的 TCP 链接资源保持并处理,每个数据库都有各自的数据协议。因此,我们通常将链接池化,以提高资源使用效率,不浪费资源。并监控活跃数闲置数总共的资源数。当资源缺少时,我们需要注意,是否是配置不足导致的资源减少。
  2. 队列:对于异步大量需要处理的任务,我们通常会使用队列,以起到削峰的作用。所以我们也会监控任务的发送量处理量Lag 值处理耗时,确保不会出现大面积的延迟进而影响业务处理的情况。
  3. 缓存:缓存框架也经常会在系统中使用,正确使用它可以减少部分数据库查询的压力,从而提升我们接口的响应性能,比如拉勾教育中就会经常用 Redis 作为部分数据的查询缓存。在缓存中,我们通常会更加关注命中率、内存使用率、数据量等指标。尤其是命中率,命中率越高表明接口性能越高,而接口性能可以缩短响应耗时。
  4. 请求:系统经常会依赖于其他需要进行 HTTP 请求等方式的第三方服务,像微信的创建订单,就需要通过 HTTP 的请求,创建订单后再返回数据。在这里同样要监控其请求数、耗时情况等指标。虽然这是个常见的现象,但在与第三方服务通信的时候,我们一定要做好熔断降级策略,最好不要因为第三方服务的不稳定导致自己业务的主流程受到阻碍。

VM 监控

我们的 Java 程序一般运行在 JVM 上,JVM 我想你一定不陌生。在 JVM 上也有很多的指标,其中有几个是需要我们关注的:

  1. GC:GC 我想应该是不用特别说明的,我们通常会收集 GC 的次数、每次 GC 时收集了多大的内存空间数据。
  2. 内存:内存可以分为年轻代、老年代、堆外、Meta 区这 4 个部分。如果老年代长期占有率较高,则有可能存在内存泄漏的问题。我们可以分别观测上面 4 个部分的当前值和最大值,来了解内存的使用量。
  3. CPU 占用率:这里指的是进程启动时 CPU 占用率,通过这个值我们可以看出这个应用是否会频繁地使用 CPU。出现问题时,如果 CPU 占用率居高不下,可能它并不是问题的根源,而仅仅是任务处理不过来。
  4. 类加载:程序启动后,一定会进行一定类的加载和卸载。监控当前总共的类加载和类卸载的数量,也是很好地观察问题的方式。如果持续出现大量的类被加载的情况,有可能是使用动态代码生成框架时出现了问题。大量的类被加载会不停地占用 Meta 区,最终导致堆溢出。
  5. 线程:线程数据也是必不可少的观察指标之一。程序代码都是运行在线程上的,如果当前活跃的线程数过多,会使 CPU 资源过高,最终因为资源占用问题,导致任务执行缓慢。我们一般会监控线程中的活跃线程数、总计线程数、等待线程数等指标。组件

组件在开发中是必不可少的内容,它们既是数据最终存储的位置,也是数据中转的地方。组件的好坏,很大程度决定了我们应用程序的好坏。在“05 课时 | 监控指标:如何通过分析数据快速定位系统隐患?(上)”中,我介绍了“组件协作资源”,里面讲到了数据库、队列和缓存资源中常见的指标,这里我再补充一个“网关层”。我们来看看这 4 个资源中的组件在运行之后,又有哪些需要监控的指标。

数据库

数据库的种类很多,比如传统的关系型数据库,还有现在比较常用的 NoSQL,都有着相当丰富的实现方式。因为它们各自的实现方式不同,所以其需要监控的指标也不同。我会列举一些它们之间相对通用的一些功能中的指标信息,一般这些指标出现问题时,会极大地影响到接口的性能。

  1. QPS:每秒查询次数。可以说每个数据库都会涉及查询请求。通过观测这个指标,我们可以很快了解到系统对数据库的查询量,以及是否需要优化查询语句。
  2. 查询耗时:查询耗时可以了解到系统的查询效率是否处于正常的区间,如果出现了“**慢查询”**现象,可以及时地处理,比如 MySQL 中可以通过增加索引来解决部分查询效率的问题,ElasticSearch 则需要筛选出查询慢的语句再逐个优化。
  3. TPS:每秒事务数。这里一般指的是对数据的添加/删除/修改操作的处理速度。TPS 不同于 QPS,它涉及修改数据,因为大多数的数据库在设计时的初衷都是以查询为主,所以 TPS 在处理时会花费更多的时间。
  4. 主从延迟数:主从的架构可以说是很多数据库都会有的一种集群方式,主从架构中有许多实现方式是基于从机器主机器上同步数据的方式来完成的,比如 MySQL。所以同步时的主从延迟数是一个十分关键的指标。延迟数高说明业务系统在读取数据时,如果恰好读到了延迟比较高的数据节点,此时系统有可能出现错误。
  5. 连接数:如果业务系统与数据库的连接达到了一定的数量,则可能造成数据库处理缓慢。因此,资源的连接数也是一个很重要的指标,一般这个指标和这个数据库的最大连接数会有一个的对比,通过这个对比可以体现出这个数据库的资源分配是否均衡。
  6. 数据量:如果数据库中单个表的数据量大于某个数值,同样会出现性能问题,比如阿里巴巴在《Java 开发手册》中规定,单表超过 500 万条数据后就要分库分表处理。一个表的数据量过大会影响查询、插入的效率,这个规定同样适用于当下的很多数据库。
  7. VM 监控:某些组件是基于某些语言开发的,因此它们还会有相对应开发语言的指标监控,比如 ElasticSearch 基于 Java 开发,所以还要监控 JVM 的信息。

除了以上这些,肯定还有很多我没有提到的指标。每个数据库不同的实现方式会细化出更多有独特性的统计指标。我所讲到的这 7 个,在各个数据库中拥有共通性,并且它们可以帮助我们初步认定一些问题的原因。

队列

在“05 课时”中我对队列有过介绍了,它通常用来处理异步和大量的任务,队列中需要监控的通用指标一般有以下 4 个:

  1. Lag:目前待消费的数据量的大小。如果这个值持续增长并且过大,则说明消费者的能力已经不能够满足生产者的生产速度了。这时候一般会考虑减少生产者生产的内容,或者加快消费者速度,如果可以的话加机器来运行也不失是一个好的选择。
  2. 发送数量:生产者生产数据的内容大小。如果这个值增长的速度越快则代表生成内容的数量越多。如果值突然飙升得比较高,也应该注意,是否存在无用内容的发送。
  3. 消费数量:消费端消费生产者内容的数量。一般的队列中间件中都会有分区的概念,通过消费数量可以清楚看到每个分区的消费情况,如果出现了某个分区消费数量明显不足的情况,则需要针对某个分区的消费实例做特殊观察。
  4. 分区数:一般在 1 个 topic 中,我们会将数据分区来提高并行消费的速度,这个分区的数量就是分区数。分区数同样是一个很关键的概念,如果一个 topic 的分区数相对较少,说明可以交给消费者消费的线程数也不多。

缓存

缓存如我之前所讲的,也是一个十分重要的部分,如果正确使用它则可以减少部分数据库查询的压力,从而提升我们接口的响应性能,缓存中也有十分多的关键指标:

  1. 响应时间:说到缓存中的关键指标,首先就要说到响应时间。一般这个指标的值都很低,因为缓存大多数时候是存储在内存中的。如果这个值偏高,说明使用方或者缓存出现了问题,这时就需要从更细的维度跟踪问题的原因了。
  2. 缓存命中率:命中率其实就是请求中查询到数据的请求请求总数,最终获得的百分比。百分比越高说明命中率越高,程序也会有更好的性能;如果命中率相对较低,则要考虑是否是写法出现了问题,或者是这个内容适不适合使用缓存。如果不适合的话可以考虑不用缓存,因为引入了一个新的组件,会增加运维和开发的成本。
  3. 网络延迟时间:对缓存来说,如果交互中出现了较高的延迟会影响到业务系统,因为缓存一般的调用频率都不低,如果延迟较高的话,会影响接口的性能,所以保证网络延迟低也是一个很关键因素。
  4. 已使用内存:缓存一般是存储在内存中的,所以对于内存的使用量有严格的要求,如果没有满足要求,缓存系统会执行淘汰策略,比如 LRU。执行淘汰策略之后可能会导致缓存命中率下降,而如果内存使用过高,缓存系统则被系统 kill。
  5. 资源链接:除了与数据库,业务系统还会与缓存系统有链接的情况,所以我们也需要监控它们的链接情况。我们常被用作缓存的 Redis,它其实也是一种 KV 类型的 NoSQL 数据库。
  6. 缓存数量:数据库中已有的缓存数量也是一个很好的指标。如果出现了使用内存达到配置阈值,导致缓存使用了一定的算法来淘汰缓存。通过缓存数量也可以清楚地看到我们系统中新增的缓存或是被移除缓存的数量对比,了解我们的系统是否是一直在有效地利用缓存提高性能。

网关层

我在“02 | 系统日志:何以成为保障稳定性的关键?”这一课时中介绍过网关层。请求从客户端过来,一般会先经过网关层,由网关层统一接收管理所有的请求。因此,在网关层也有一些指标是可以监控的:

  1. 请求相关:同我在“05 课时”中讲应用程序中的指标时一样,在网关层你也需要关注 QPS、状态码、请求耗时等信息。网关层里往往会记录请求整体的执行情况。这里的数据肯定是最全、最准的。
  2. 错误数:如果网关层出现了错误请求信息,由于网关层是高于应用层的,所以应用层中的请求一般是由网关层转发,信息根本不会进入应用层。所以当在网关层出现错误数飙升的问题时,在应用层可能根本无法定位问题的原因。
  3. 请求处理:网关层有相关的请求处理机制,所以监控请求处理相关的数据也十分关键,比如总请求数、正处于“读”状态的请求数、正处于“写”状态的请求数、正在排队的请求数。如果出现大量的排队现象,则说明网关层已经处理不过来了,这时候一般可以通过增加网关机器来解决。

机器信息

最后我们来说说机器的统计信息。机器的处理性能如果不够好,会直接影响服务的运行情况,毕竟服务是依托机器运行。机器信息的指标可以按照组成部分,分为以下几个:

  1. CPU:CPU 的运行情况肯定是应用程序中最重要的。我们一般会比较关注 CPU 的整体使用率,然后再细分为系统侧用户侧的使用率。同样,我们也会关注系统的 Load 情况,如果 Load 值越高说明系统承受的处理任务越多,系统执行也会更缓慢。
  2. 内存:内存的大小会影响程序的可使用内存空间,除了重内存使用程序。内存中我们也会关注内存的整体使用率,以及 swap 区的使用率。一般我不太建议使用 swap 区,因为它会利用磁盘的空间来代替内存,而这可能会影响到程序的使用性能。如果 swap 区的使用率较高,可以考虑将其关闭,通过升级内存来提高程序性能。
  3. 磁盘:在一般的应用程序中,磁盘更多的是用于日志记录临时缓存文件记录。同 CPU 和内存一样,关注磁盘的使用率即可。
  4. 网络:网络情况可以说是现在应用中的重中之重,无论是链接组件还是微服务中的 RPC,到处都有服务器之间的通信。一般我们会更关注出/入流量,如果当到达网卡限制的大小后,则一般只能考虑扩容服务来解决,因为网卡的提升是有限的。在此之外,我们还会监控网络丢包率连接错误数等信息,这些信息可以帮助我们的程序在网络出现问题时,判断是否是网卡的原因。
  5. I/O:在 Linux 平台中,任何的网络请求、消息或是其他内容都是基于文件来构成的,所以 I/O 在 Linux 中无处不在。我们会更关注 I/O 的文件读取/写入中的速度耗时次数等信息,这些都是最能直观体现出写入和读取速度的内容。同时我们还会关注使用率(util),如果磁盘的使用率过高,则说明应用对磁盘的使用量很大,很有可能会因为磁盘的问题而导致应用程序上的问题。
  6. 句柄:随着 I/O 的使用,我们也需要关注句柄的使用量。如果程序中出现了资源流未关闭的情况,则有可能会导致句柄数激增,最终导致句柄耗尽,影响程序执行。在“04 | 统计指标:"五个九"对系统稳定的意义?”这一课时中,我就说到了之前我们就曾出现过因 HTTP 中流未关闭,使句柄耗尽,导致程序无法再次发起 HTTP 请求。

结语

至此,对监控指标的介绍就告一段落了,从用户侧到服务器,我向你介绍端上访问、应用程序、组件、机器信息中需要监控的指标以及常见的问题状况及解决办法,希望能对你的工作有一定的帮助。那么,你认为在组件和机器中还有哪些你经常关注的指标?

指标是保证系统稳定不可或缺的一环,它同日志一样,在每个端都有很多的指标数据。

展开阅读全文

页面更新:2024-04-01

标签:数据   分布式   缓存   隐患   指标   快速   情况   数据库   时间   内容   用户   系统   资源   技术

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号

Top