架构随着分布式架构逐渐成为主流,“可观察性”这个词也被越来越频繁的提及。它涵盖的范围很广,主要归纳为以下三类:聚合指标(metrics)、事件日志(logging)和链接跟踪(tracing)这三个方向虽然各有千秋,但也不是完全独立的。PeterBourgon的文章《Metrics, Tracing, and Logging》系统地阐述了这三者的定义和特点,以及它们之间的关系和区别,得到了业界的广泛认可。在实际工作中,大家或多或少对以上三者都有一定的了解,但没有机会也没有深入研究的必要。Metrics是一种度量单位,是指对系统中的某个指标进行统计聚合,然后将这些信息进行聚合,以揭示系统的整体运行状况。指标一般可以分为三个相对独立的过程:客户端指标采集、服务端存储查询、终端监控预警。每个过程一般由不同的组件完成。以Prometheus为例:指标可以直接由各种exporter抓取,也可以从pushgateway抓取,然后存入TSDB(时序数据库)。查询指标可以通过grafana或者prometheusweb传递,通过altermanager实现告警。可见,一个测量工具的内部实现是非常复杂的,使用时会消耗一定的资源。目前,Prometheus在云原生领域占据主导地位。严格来说,已经成为云原生监控的标配。下面主要以Prometheus为例进行介绍。指标采集指标采集主要包括两部分:指标定义指标采集比指标采集更重要,一个好的指标定义可以更直观的反映系统状态。最常用的黄金指标是:延迟:延迟是消息发送方和接收方之间的时间延迟,以毫秒(ms)为单位。其原因通常是由于数据包丢失、网络拥塞和称为“数据包延迟方差”的网络抖动。延迟直接影响客户体验,转化为成功请求的延迟和失败请求的延迟。流量:流量是由系统上完成的工作量造成的压力。它以每秒查询数(QPS)或每秒事务数(TPS)来衡量。企业用数字来衡量这一点:关键绩效指标(KPI)是在给定时间访问网站的人数。这与商业价值有直接关系。错误:错误是根据整个系统中发生的错误来衡量的。什么是服务错误率的重要指标!有两种类型的错误,显式错误,例如失败的HTTP请求(例如,500错误代码)。而隐式错误将是成功的响应,但内容错误或响应时间长。饱和度:饱和度定义了服务的超载程度。它衡量系统利用率,强调资源和服务的整体能力。这通常适用于CPU使用率、内存使用率、磁盘容量和每秒操作数等资源。仪表板和监控警报是帮助您关注这些资源并帮助您在容量饱和之前主动调整容量的理想工具。利用:虽然不是“四大黄金信号”的一部分,但值得一提;利用率表示资源或系统的繁忙程度。它以%(百分比)表示,范围为0–100%。因此,在定义指标时,可以结合以上黄金指标进行分类,但并不意味着每一类应用都需要满足以上所有指标。以系统监控为例,说明是否需要监控该类指标:定义资源指标后,定义获取该指标的具体方法。目前有很多基于Prometheus监控实现的Exporter。这些Exporter基本上可以得到我们想要的指标,例如:指标查询指标被Prometheus采集后,会存储到它的TSDB(时序数据库)中。我们可以使用Prometheus在Web上查询需要的指标如下,获取kubelet在不同时间节点的HTTP请求总数:监控预警指标测量是一种手段,最终目的是做分析和提早警告。我们可以利用这些指标打造一个监控大屏,随时观察系统的状态。Kubernetes中容器和节点的状态可以实时监控如下:良好的可视化能力对于提高度量系统的产品力非常重要。长期趋势分析(例如根据磁盘增长趋势的观察来判断何时需要扩容),对比分析(例如版本升级后新旧版本在性能和资源消耗上的差异),故障分析(不仅是自下而上的日志和迹线分析,从高维的Metrics也可能自上而下的寻找问题的蛛丝马迹)等分析工作需要的不仅是对数据的持续收集和统计指标,也是数据的可视化,让人更容易从数据中挖掘规律。还可以对重要指标进行告警,便于维护人员及时介入,排除故障。下面是应用JVM使用过载的告警。但是,在进行报警时,需要综合考虑指标的重要性。并不是所有的指标都需要报警,否则很容易引起报警风暴,最后《狼来了》的故事才会被真正演绎出来。事件日志(Logging)日志用于记录系统运行过程中发生的事件,每个系统都应该有日志。日志是排查问题的重要手段。大多数系统问题最终都会追溯到日志,所以良好的日志记录可以帮助快速定位系统问题。但是目前微服务基本是以多节点的形式存在的,没有办法像单机时代那样简单的使用命令来获取日志内容。而是需要将日志收集到专门的日志系统中,然后进行查询和分析。目前比较流行的开源日志系统是ELK或者EFK,在日志领域有着不可动摇的地位。事件日志还涉及到以下几个方面:日志输出日志采集日志查询日志报警日志输出万千开发可能有一千种日志输出方式,而且输出的内容千奇百怪,不管重要不重要都输出到日志中,这样会使查看日志变得困难,造成很大的干扰。因此,良好的登录习惯非常重要。企业中应该有专门的日志规范,这样格式和标准就可以统一,既有利于收藏,也有利于查看。打印日志时尽量做到:记录请求的TraceID,记录关键事件,包括上下文,不打印敏感信息,合理规划日志级别,收集日志。对于分布式服务,为了同时看到跨节点的所有日志,各个节点统一收集各种日志,比如使用Logstash或者Filebeat来收集日志,在收集日志的同时处理日志。例如,可以为同一个应用的日志建立索引,可以每天为同一个应用创建索引。避免索引过大导致的查询困难等问题。如果在日志采集过程中发现日志比较大,可以在采集过程中先将日志写入缓存或者消息队列,避免直接写入Elasticsearch造成其压力过载。日志查询收集的日志最终存储在Elasticsearch中,通常与Kibana配合使用,方便用户操作。虽然Kibana只负责图形界面和显示,但它提供的功能远远超出允许您在界面上执行Elasticsearch查询。Kibana推广的核心能力是“探索数据、可视化”,即对存储在Elasticsearch中的数据进行检索、聚合、统计后,定制形成各种图形、表格、指标、统计数据,以供观察系统运行状态,发现日志事件中隐藏的规则和隐患。按照Kibana官方的slogan,“一张图片抵得上千万行日志”。日志告警在进行日志输出时,需要对一些具有破坏性的日志进行特殊标记,遇到此类日志需要及时通知维护人员。我们可以使用ElastAlert进行告警处理。ElastAlert是一个三方插件,通过查询ElasticSearch来比对记录,通过配置告警规则对符合规则的日志进行告警。ElastAlert将Elasticsearch与两种类型的组件(规则类型和警报)结合使用,定期查询Elasticsearch,并将数据传递给规则类型,规则类型确定何时找到匹配项。当匹配发生时,将为该警报提供一个或多个警报,该警报将根据匹配进行操作。链接跟踪(Tracing)有指标和日志,在大多数情况下足以满足日常使用,但它们有一个缺点,即不能直观地查看上下文,也不能有效地跟踪请求。因此,引入了链接跟踪。从目标来看,链路追踪的目的是为故障排除和性能分析提供数据支持。系统在对外提供服务的过程中,不断接受请求和处理响应,同时不断产生痕迹,将每一条痕迹按顺序整理。一个Span记录的调用关系可以画出系统服务调用拓扑图。根据Span在拓扑图中记录的时间信息和响应结果(正常或异常返回),可以定位缓慢或错误的服务;通过Trace和历史记录的对比统计,可以从系统整体层面分析服务性能,定位性能优化的目标。从字面上看,链路监控的实现比较简单,但在实际工作中比较复杂。主要原因是企业业务系统可能使用不同的编程语言,每种编程语言的实现方式不同,导致工作量巨大,同时还要考虑以下几点:低损耗:如果接入链路监控是不仅没有解决问题,反而增加了性能开销,得不偿失。透明:尽量不要增加开发的工作量,最好做到无侵入访问。易用性:傻瓜式使用更受欢迎。目前最常用的有Zipkin、Skywalking、Pinpoint等,都是基于服务跟踪实现的。服务跟踪的思路是通过某种手段向目标应用程序中注入一个跟踪探针(Probe),而对于Java应用程序,一般是通过JavaAgent注入。探针的结构可以看作是一个寄生在目标服务上的小型微服务系统。它一般都有自己专用的服务注册、心跳检测等功能,并有专门的数据采集协议。服务调用信息通过另一个独立的HTTP或RPC请求发送到跟踪系统。以下是使用Skywalking收集的查询页面。最后,可观察性平台是一个非常庞大和复杂的平台。大多数公司使用一些开源方法来堆叠它们。虽然它们可以解决一些问题,但它们相互独立,不能友好地连接起来。这也导致排查问题时需要在各个平台之间切换,每个平台都需要一定的学习成本,这也导致很多公司安装部署,但在实践中却很少使用,达不到预期效果影响。链接[1]https://peter.bourgon.org/blog/2017/02/21/metrics-tracing-and-logging.html[2]https://skywalking.apache.org/[3]https://www.elastic.co/cn/
