架构10-可观测性
1、可观测性
(1)可观测性的背景
- **历史沿革:**可观测性最初由匈牙利数学家鲁道夫·卡尔曼提出,用于线性动态控制系统。后来,该概念被引入到计算机科学中。
- **现代意义:**在分布式系统和云原生时代,可观测性成为不可或缺的属性,与可并发性、可用性、安全性等并列,成为系统的非功能属性之一。
(2)可观测性的定义与特征
- **定义:**可观测性是指“可以由系统的外部输出推断其内部状态的程度”。
- 三个方向:
- **日志收集:**记录离散事件,通过这些记录事后分析出程序的行为。
- **链路追踪:**主要用于排查故障,分析调用链的哪一部分、哪个方法出现错误或阻塞,输入输出是否符合预期。
- **聚合度量:**对系统中某一类信息的统计聚合,主要用于监控和预警,当某些度量指标达到风险阈值时触发事件。
(3)工业界的遥测产品
- 日志领域:
- Elastic Stack (ELK):目前主导日志收集和分析的技术栈。
- Fluentd:有取代Logstash的趋势,形成EFK技术栈。
- 度量领域:
- Prometheus:在云原生时代成为度量监控的事实标准,社区活跃度高。
- 追踪领域:
- **特性:**与具体网络协议、程序语言密切相关,具有较强的侵入性。
- 主流产品:
- Datadog:一揽子商业方案。
- AWS X-Ray 和 Google Stackdriver Trace:云计算厂商产品。
- SkyWalking、Zipkin、Jaeger:开源社区产品。
- 发展趋势:
- OpenTelemetry:融合日志、追踪、度量三者所长,有望成为统一可观测性的解决方案。
2、日志收集
(1)日志的基本概念
- **定义: **日志主要用于记录系统运行期间发生的离散事件。
- **普遍性: **几乎所有的生产系统都会有日志功能,但往往不被重视。
(2)日志的重要性
- **记录信息: **日志能够记录系统运行的关键信息,帮助诊断问题。
- **复杂性: **随着系统复杂度的增加,日志的管理和分析变得越来越重要。
(3)日志的输出
- **概念 **
- 输出是日志处理的第一步,也是最基础的步骤。良好的日志输出不仅能够帮助开发者和运维人员快速定位问题,还能为后续的分析和监控提供可靠的数据源。
- 输出的基本原则
- 格式统一
- **格式一致:**日志的格式应该统一,便于后续的解析和处理。常见的格式包括 JSON、CSV 等。
- **字段规范:**日志中应该包含必要的字段,如时间戳、日志级别、服务名、请求 ID 等。
- 内容恰当
- **内容适当:**日志内容应该既不过多也不过少,关键在于“恰当”。
- 不该出现的内容不要有:
- 敏感信息:避免将密码、银行账号、身份证号等敏感信息记录到日志中。这些信息一旦泄露,将带来严重的安全风险。
- **调试信息:**避免在生产环境中输出大量的调试信息,如方法输入参数、输出结果、方法执行时长等。这些信息不仅占用大量存储空间,还可能暴露敏感数据。
- **堆栈信息:**除非必要,否则不要在日志中输出完整的堆栈信息。这可能会导致误判,增加问题排查的难度。
- 该出现的内容不要少:
- **TraceID:**在分布式系统中,每个请求应该有一个唯一的 TraceID,用于追踪请求在各个服务节点中的执行情况。
- **重要事件:**系统进行的操作、异常情况、未处理的异常或警告、定期任务等重要事件都应该记录在日志中。
- **配置信息:**系统启动时或配置发生变化时,应将非敏感的配置信息输出到日志中,便于后续的诊断和复现。
- 日志级别
- **合理选择日志级别:**根据事件的重要程度,选择合适的日志级别(如 DEBUG、INFO、WARNING、ERROR、FATAL)。这有助于在日志量较大时,快速定位关键信息。
- **动态调整日志级别:**在生产环境中,可以根据需要动态调整日志级别,以减少对性能的影响。
- 性能考虑
- **避免过度输出:**虽然日志记录很重要,但过度输出会影响系统性能。可以通过采样、限流等手段,控制日志输出的数量。
- **异步输出:**使用异步日志框架(如 Logback 的 AsyncAppender),减少日志输出对主业务流程的影响。
- 工具和框架
- **日志框架:**选择合适的日志框架,如 SLF4J、Log4j、Logback 等,这些框架提供了丰富的功能和良好的扩展性。
- **MDC:**使用 Mapped Diagnostic Context(MDC)机制,可以在日志中自动添加上下文信息,如用户 ID、请求 ID 等。
- 示例:假设我们正在开发一个 Web 应用,以下是一个合理的日志输出示例:
timestamp
:记录日志的时间戳。level
:日志级别,这里是 INFO。service
:服务名,便于区分不同的服务。traceId
:唯一的请求 ID,用于追踪请求。userId
:用户 ID,便于后续分析。message
:日志的具体内容。
{"timestamp": "2023-10-01T12:34:56.789Z","level": "INFO","service": "user-service","traceId": "1234567890abcdef","userId": "user123","message": "User login successful"
}
(4)日志的收集与缓冲
- 收集
- **目的:**将分布在各个服务节点上的日志文件统一收集起来,集中存储和索引,以便进行全局查询和分析。
- **背景:**在分布式系统中,一个请求可能会跨越多个服务节点,因此需要一个全局的日志系统来覆盖整个调用链路。
- 工具:
- **Logstash:**最初 ELK(Elastic Stack)中的日志收集和加工聚合工作都是由 Logstash 承担的。Logstash 既可以作为收集的客户端(Shipper)部署在各个节点上,也可以作为服务端(Master)独立部署。
- **Filebeat:**后来,Elastic.co 公司推出了基于 Libbeat 框架的 Filebeat,使用 Golang 重写,更加轻量高效,适合在每个服务节点上部署。
- **Community Beats:**社区维护的大量 Beats 插件,可以收集各种不同类型的数据,使得 ELK 在一定程度上可以替代度量和追踪系统。
- 缓冲
- **目的:**缓解日志收集和处理过程中可能出现的性能瓶颈,保证日志数据的连续性和完整性。
- **挑战:**在大型分布式系统中,日志量非常大,例如淘宝每天的日志量超过 10PB,日志收集器的部署实例数达到百万量级,保持日志数据的绝对一致性非常困难。
- 解决方案:
- **队列缓存:**在 Logstash 和 Elasticsearch 之前,架设一个抗压能力更强的队列缓存,如 Kafka 或 Redis。
- 作用:
- **削峰填谷:**当 Logstash 或 Elasticsearch 处理能力出现瓶颈时,队列缓存可以暂时存储日志数据,防止数据丢失。
- **提高可靠性:**即使 Logstash 或 Elasticsearch 短时间停顿,也不会丢失日志数据。
- 关键点
- **数据覆盖:**日志收集器必须覆盖所有数据来源,确保日志数据的完整性和连续性。
- **性能优化:**通过轻量级的收集器(如 Filebeat)和抗压能力强的队列缓存(如 Kafka),优化日志处理的性能。
- **数据质量:**在可承受的代价范围内,尽可能保证较高的数据质量,而不是追求绝对的完整精确。
(5)日志的加工与聚合
- 加工
- 目的:
- **结构化数据:**将非结构化的日志数据转换为结构化数据,以便于后续的查询、统计和聚合。
- **数据清洗:**去除无效或无关的信息,确保数据的质量。
- **数据增强:**添加额外的元数据或信息,使数据更加丰富和有用。
- 工具:
- **Logstash:**Elastic Stack 中的核心组件之一,主要用于日志数据的加工和转换。
- **Grok 表达式:**Logstash 使用 Grok 表达式来解析和提取日志中的字段。
- 具体步骤:
- **解析日志行:**使用 Grok 表达式将日志行中的各个字段解析出来。
- **数据清洗:**去除无效或无关的信息,例如删除不必要的日志行或字段。
- **数据转换:**将解析出的字段转换为合适的格式,例如将时间戳转换为统一的时间格式。
- **数据增强:**添加额外的元数据,例如将 IP 地址转换为地理位置信息。
- **示例:**假设有一行 Nginx 服务器的 Access Log:
14.123.255.234 - - [19/Feb/2020:00:12:11 +0800] "GET /index.html HTTP/1.1" 200 1314 "https://icyfenix.cn" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
* 使用 Grok 表达式可以将其解析为以下结构化数据:
{"ip": "14.123.255.234","timestamp": "19/Feb/2020:00:12:11 +0800","request": "GET /index.html HTTP/1.1","status": 200,"size": 1314,"referrer": "https://icyfenix.cn","user_agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
}
- 聚合
- 目的:
- **统计分析:**从大量的日志数据中提取有用的统计信息。
- **数据可视化:**将统计结果以图表等形式展示,便于观察和分析。
- 工具:
- **Elasticsearch:**提供强大的聚合功能,可以进行实时的统计分析。
- **Logstash:**可以在数据处理过程中生成固定的聚合指标。
- 具体步骤:
- **实时聚合:**使用 Elasticsearch 的聚合功能进行实时的统计分析。
- **固定聚合:**在 Logstash 中通过聚合插件生成固定的聚合指标。
- **示例:**假设我们想从 Nginx 的 Access Log 中统计每小时的请求数量和响应状态码的分布。
- **实时聚合:**使用 Elasticsearch 的聚合查询:
GET /nginx_access_logs/_search
{"size": 0,"aggs": {"requests_per_hour": {"date_histogram": {"field": "timestamp","calendar_interval": "hour"}},"status_codes": {"terms": {"field": "status"}}}
}
- **固定聚合:**在 Logstash 中配置聚合插件,生成固定的聚合指标:
input {file {path => "/var/log/nginx/access.log"}
}filter {grok {match => { "message" => "%{COMBINEDAPACHELOG}" }}date {match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]}aggregate {task_id => "%{[@metadata][aggregate_id]}"code => "map['requests'] ||= 0; map['requests'] += 1"timeout => 3600timeout_code => "event.set('requests', event.get('requests'))"timeout_tags => ["aggregated"]}
}output {elasticsearch {hosts => ["localhost:9200"]index => "nginx_aggregated_logs"}
}
(6)日志的存储与查询
- Elasticsearch 的核心地位
- Elasticsearch 是 Elastic Stack 技术栈的核心组件,专门用于日志分析。
- 优势:
- **优秀的全文检索能力:**适合处理非结构化的日志数据。
- **近实时性:**日志数据可以在生成后不久即可被查询,满足实时监控的需求。
- **高扩展性:**支持水平扩展,可以处理大规模的日志数据。
- 时间范围索引
- **时间特性:**日志数据是基于时间的数据流,已写入的数据很少会变动。
- 索引策略:
- **按时间范围索引:**通常按日、周、月等时间单位创建索引。
- **预创建索引:**可以提前创建未来的索引,避免动态创建带来的开销。
- **索引别名:**使用
logs_current
这样的别名指向当前索引,方便管理和查询。
- 冷热数据分离
- **数据价值:**日志数据的价值随着时间的推移逐渐降低。
- 硬件策略:
- **热数据:**使用高性能的 SSD 磁盘和强大的处理器。
- **冷数据:**使用低成本的 HDD 磁盘和较弱的处理器,甚至可以归档到对象存储(如阿里云的 OSS、腾讯云的 COS、AWS 的 S3)中。
- 查询能力
- **API 层面:**Elasticsearch 提供了丰富的 API,支持复杂的查询和聚合操作。
- Kibana 集成:
- **图形界面:**Kibana 是 Elastic Stack 的 GUI 部分,提供友好的操作界面。
- **数据探索与可视化:**Kibana 支持数据的探索、可视化,帮助用户快速发现系统中的问题和趋势。
- 应用场景
- **可观测性:**日志在系统可观测性方面的作用,主要用于监控和故障排查。
- **大数据挖掘:**虽然日志也可以用于业务热点分析、用户习惯分析等大数据挖掘场景,但这些场景更可能采用 HBase 与 Spark 的组合,而不是 Elastic Stack。
3、链路追踪
(1)追踪与跨度
- **追踪 (Trace):**从客户端发起请求抵达系统的边界开始,记录请求流经的每一个服务,直到向客户端返回响应为止,这整个过程称为一次 追踪(Trace)。
- **跨度 (Span):**每次开始调用服务前,系统都会先埋入一个调用记录,这个记录称为一个 跨度(Span)。Span 用于记录具体调用了哪些服务,以及调用的顺序、开始时点、执行时长等信息。
- Span 的数据结构应该具备以下特点:
- **简单性:**足够简单,以便于能放在日志或者网络协议的报文头里。
- **完备性:**至少包含时间戳、起止时间、Trace 的 ID、当前 Span 的 ID、父 Span 的 ID 等信息。
- 追踪树 (Trace Tree)
- 每次 Trace 都是由若干个有顺序、有层级关系的 Span 组成的一颗 追踪树(Trace Tree)。
- 追踪树的结构如下图所示:
Trace
├── Span 1
│ ├── Span 1.1
│ └── Span 1.2
└── Span 2 └── Span 2.1
(2)追踪的目标与实现
- 目的
- **故障排查:**通过追踪记录的时间信息和响应结果(正常或异常返回),可以定位到缓慢或者出错的服务。
- **性能分析:**将 Trace 与历史记录进行对比统计,可以从系统整体层面分析服务性能,定位性能优化的目标。
- 实现
- **低性能损耗:**分布式追踪不能对服务本身产生明显的性能负担。
- **对应用透明:**追踪系统通常是运维期才事后加入的系统,应尽量以非侵入或者少侵入的方式来实现追踪,对开发人员做到透明化。
- **随应用扩缩:**现代的分布式服务集群有根据流量压力自动扩缩的能力,追踪系统也应能自动跟随。
- **持续的监控:**追踪系统必须能够 7x24 小时工作,以定位系统偶尔抖动的行为。
(3)数据收集
- 基于日志的追踪 (Log-Based Tracing)
- 优点:
- **低侵入性:**对网络消息完全没有侵入性,对应用程序只有少量的侵入性。
- **低性能损耗:**对性能的影响非常低。
- 缺点:
- **依赖日志归集:**直接依赖于日志归集过程,日志本身不追求绝对的连续与一致,可能导致追踪不够精准。
- **延迟和缺失:**业务服务的调用与日志的归集不是同时完成的,可能导致日志出现延迟或缺失记录,从而产生追踪失真。
- 应用场景:
- 适用于中小型应用,尤其是对性能敏感的应用。
- 适合对追踪精度要求不高的场景。
- 代表产品:Spring Cloud Sleuth
调用端日志输出:
Created new Feign span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable: false ]
2019 -06 -30 09 : 43 : 24.022 [http - nio -9010 - exec -8 ] DEBUG o.s.c.s.i.web.client.feign.TraceFeignClient - The modified request equals GET http: / / localhost: 9001 / product / findAll HTTP / 1.1 X - B3 - ParentSpanId: cbe97e67ce162943 X - B3 - Sampled: 0 X - B3 - TraceId: cbe97e67ce162943 X - Span - Name: http: / product / findAll X - B3 - SpanId: bb1798f7a7c9c142 服务端日志输出:
[findAll] to a span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable: false ]
Adding a class tag with value [ProductController] to a span [Trace: cbe97e67ce162943, Span: bb1798f7a7c9c142, Parent: cbe97e67ce162943, exportable: false ]
- 基于服务的追踪 (Service-Based Tracing)
- 优点:
- 高精确性:追踪的精确性与稳定性都有所保证,不必再依靠日志归集来传输追踪数据。
- 详细信息:可以获取详细的调用信息,如参数、变量等方法级调用信息。
- 缺点:
- **资源消耗:**会比基于日志的追踪消耗更多的资源,具有较强的侵入性。
- **性能压力:**对应用系统的性能压力较大,一般仅在除错时开启。
- 应用场景:
- 适用于需要高精度追踪的场景。
- 适合大型系统,尤其是在除错和性能分析时。
- 代表产品:
- 示例截图:
- Pinpoint 的追踪效果截图展示了详细的调用信息,包括参数、变量等。
- 基于边车代理的追踪 (Sidecar-Based Tracing)
- 优点:
- 完全透明:对应用完全透明,无论是日志还是服务本身都不会有任何变化。
- 语言无关:与程序语言无关,无论应用采用什么编程语言实现,只要通过网络访问服务,就可以被追踪到。
- **独立数据通道:**有自己独立的数据通道,避免了追踪对程序通信或日志归集的依赖和干扰,保证了最佳的精确性。
- 缺点:
- **服务网格普及度:**目前服务网格还不够普及,限制了其广泛应用。
- **服务调用层面:**只能实现服务调用层面的追踪,无法实现本地方法调用级别的追踪诊断。
- 应用场景:
- 适用于云原生环境,尤其是使用服务网格的场景。
- 适合对追踪透明度和精确性要求极高的场景。
- 代表产品:
- Envoy
- SkyWalking
- Zipkin
- Jaeger
- LightStep Tracing
- 示例集成:
- Envoy 作为边车代理,可以与 SkyWalking、Zipkin 等系统集成,充当数据收集端。
(4)追踪规范化
- 追踪规范化的背景与重要性
- 背景
- **Dapper 论文的影响力:**Google 发表的 Dapper 论文为分布式追踪系统提供了基础思路,但并未形成有约束力的标准。这导致市场上出现了多种追踪系统,如 Zipkin、SkyWalking、Pinpoint 等,它们虽然功能相似,但互不兼容。
- **市场竞争激烈:**追踪领域的竞争比日志和度量更为激烈,没有一家公司或产品占据主导地位。各家公司都在努力推出自己的追踪系统,导致市场碎片化。
- 重要性
- **互操作性:**规范化可以确保不同厂商的追踪系统能够互相通信和协作,减少用户的迁移成本。
- **标准化:**规范化的标准可以为追踪系统的开发和集成提供统一的指导,促进技术的发展和创新。
- **生态系统建设:**通过规范化,可以吸引更多开发者和企业参与到追踪系统的生态建设中,推动整个行业的进步。
- **主要的追踪规范 **
- OpenTracing
- **概述:**OpenTracing 是一套与平台无关、与厂商无关、与语言无关的追踪协议规范。它旨在提供一个标准化的层,位于应用程序与追踪系统之间,使得不同的追踪系统可以互相通信。
- 特点:
- **标准化层:**提供了一个薄的标准化层,使得探针和追踪系统可以互相通信。
- **跨语言支持:**支持多种编程语言,确保不同语言的应用程序可以使用相同的追踪标准。
- **API 规范:**定义了微服务之间在发生调用时如何传递 Span 信息(OpenTracing Payload)。
- OpenCensus
- **概述:**OpenCensus 是由 Google 提出的另一套追踪和度量规范。它不仅涉及追踪,还涵盖了指标度量,并提供了数据采集的探针和收集器。
- 特点:
- **综合性:**不仅包括追踪,还涵盖了度量,提供了一个更全面的可观测性解决方案。
- **SDK 支持:**提供了多种语言的 SDK,方便开发者集成。
- **数据采集:**不仅定义了规范,还提供了数据采集的工具和库。
- OpenTelemetry
- **概述:**OpenTelemetry 是 OpenTracing 和 OpenCensus 合并后的产物,旨在统一追踪、度量和日志三大领域的规范。
- 特点:
- **统一性:**整合了 OpenTracing 和 OpenCensus 的优势,提供了一个更全面的可观测性解决方案。
- **广泛支持:**得到了众多厂商的支持,包括 Google、Microsoft 等。
- **模块化:**包括了追踪规范、度量规范、日志规范、各种语言的 SDK 以及采集系统的参考实现。
- **社区活跃:**作为一个 CNCF 孵化项目,OpenTelemetry 拥有活跃的社区和丰富的资源。
- 追踪规范化的发展趋势
- 统一标准
- **OpenTelemetry 的崛起:**OpenTelemetry 的出现标志着追踪规范化的一个重要里程碑。它不仅整合了 OpenTracing 和 OpenCensus 的优势,还得到了广泛的行业支持,有望成为未来的标准。
- **厂商支持:**越来越多的厂商和项目开始支持 OpenTelemetry,包括 Zipkin、Jaeger、SkyWalking 等。
- 生态系统扩展
- **工具和库的丰富:**随着 OpenTelemetry 的普及,相关的工具和库也在不断丰富,为开发者提供了更多的选择。
- **社区贡献:**活跃的社区贡献使得 OpenTelemetry 不断完善,新的功能和改进持续推出。
- 未来展望
- **标准化的推进:**随着 OpenTelemetry 的发展,追踪系统的标准化将进一步推进,互操作性和生态系统的建设将更加完善。
- **技术创新:**规范化为技术创新提供了基础,未来可能会出现更多创新的追踪技术和解决方案。
4、聚合度量
(1)度量的定义
- **计数度量器(Counter):**对有相同量纲、可加减数值的合计量,例如销售额、服务调用次数等。
- **瞬态度量器(Gauge):**表示某个指标在某个时点的数值,例如当前内存使用量、网站在线人数等。
- **吞吐率度量器(Meter):**统计单位时间的吞吐量,例如TPS(每秒事务数)、港口的货运吞吐率等。
- **直方图度量器(Histogram):**记录具体数值的二维统计图,例如GDP变化情况。
- **采样点分位图度量器(Quantile Summary):**评估理论值与实际值之间的拟合度,例如高考成绩分布。
(2)指标收集
- 核心思想
- **如何定义指标:**确定需要收集哪些指标及其数据类型。
- **如何将这些指标告诉服务端:**选择合适的采集方式将指标数据传递给服务端。
- **如何定义指标:**定义指标时,需要考虑以下几种常见的度量器类型:
- 计数度量器(Counter):
- **定义:**对有相同量纲、可加减数值的合计量。
- **示例:**销售额、货物库存量、职工人数、服务调用次数、网站访问人数等。
- 瞬态度量器(Gauge):
- **定义:**表示某个指标在某个时点的数值,不需要进行加减统计。
- **示例:**Java 虚拟机堆内存的使用量、网站在线人数等。
- 吞吐率度量器(Meter):
- **定义:**用于统计单位时间内的吞吐量,即单位时间内某个事件的发生次数。
- **示例:**交易系统的 TPS(每秒事务交易数)、港口的货运吞吐率(吨/每天)等。
- 直方图度量器(Histogram):
- **定义:**常见的二维统计图,记录具体数值。
- **示例:**经济报告中,以 GDP 为纵坐标、时间为横坐标构成的直方图。
- 采样点分位图度量器(Quantile Summary):
- **定义:**通过比较各分位数的分布情况,评估理论值与实际值之间的拟合度。
- **示例:**高考成绩的正态分布情况。
- 除了上述常见的度量器之外,还有 Timer、Set、Fast Compass、Cluster Histogram 等其他类型的度量器。不同的度量系统支持的度量器类型可能会有所不同,例如 Prometheus 支持 Counter、Gauge、Histogram 和 Summary 四种度量器。
- 将指标传递给服务端通常有两种解决方案:
- 拉取式采集(Pull-Based Metrics Collection):
- **定义:**度量系统主动从目标系统中拉取指标。
- **优点:**简化了目标系统的实现,减少了目标系统的负担。
- **缺点:**目标系统需要对外提供可访问的端点,适用于目标系统较为稳定的情况。
- **示例:**Prometheus 默认采用 Pull 方式。
- 推送式采集(Push-Based Metrics Collection):
- **定义:**目标系统主动向度量系统推送指标。
- **优点:**适用于目标系统位于内网或生命周期较短的情况。
- **缺点:**增加了目标系统的实现复杂度。
- **示例:**Ganglia、Graphite、StatsD 等。
- 兼容性解决方案Push Gateway:
- **定义:**位于 Prometheus Server 外部的中介模块,用于暂存目标系统推送的指标。
- **作用:**解决 Pull 的一些固有缺陷,如目标系统位于内网、短生命周期服务等。
- **工作原理:**目标系统将指标推送到 Push Gateway,Prometheus Server 从 Push Gateway 中拉取指标。
- 网络访问协议和数据结构
- **标准协议:**虽然定义标准协议(如 SNMP、WMI、JMX)在特定领域内有应用,但缺乏广泛适用性。
- **HTTP 访问:**Prometheus 采用 HTTP 访问度量端点的方式,目标系统需要提供符合 Prometheus 格式的 HTTP 端点。
- **Exporter:**对于不支持 HTTP 端点的目标系统,可以使用 Exporter 作为中介,将指标转换为 Prometheus 格式。
(3)存储查询
- 存储挑战
- **数据量巨大:**在一个中等规模的微服务系统中,每天生成的度量数据量可能达到数十亿条记录。
- **写多读少:**度量数据通常是频繁写入,但读取相对较少。
- **数据不可变:**度量数据一旦写入,很少会被修改或删除。
- **数据有序:**度量数据按时间顺序生成,需要高效的时间范围查询能力。
- 存储解决方案
- 时序数据库的特点
- **数据结构简单:**每个度量指标由时间戳、名称、值和一组标签构成。
- **写操作为主:**数据通常是追加写入,很少进行修改或删除。
- **时间索引:**数据按时间顺序存储,支持高效的时间范围查询。
- **数据压缩:**通过压缩技术减少存储空间占用。
- **数据保留策略:**根据数据的重要性和查询需求,设置数据保留时间,过期数据自动删除。
- 典型的时序数据库
- **Prometheus:**内置了一个强大的时序数据库,使用 LSM-Tree 结构,支持高效的写操作和查询。
- **InfluxDB:**提供类 SQL 风格的查询语言,广泛用于物联网和监控场景。
- **OpenTSDB:**基于 HBase 构建,适用于大规模集群环境。
- **TimescaleDB:**基于 PostgreSQL 的扩展,支持 SQL 查询,适合需要复杂查询的场景。
- 存储优化技术
- **LSM-Tree:**Log Structured Merge Tree 是一种专门为写多读少场景设计的存储结构,能够高效处理大量的写操作。
- **数据保留策略:**根据数据的重要性和查询需求,设置合理的数据保留时间,过期数据自动删除,节省存储空间。
- **数据重采样:**对历史数据进行重采样,减少存储空间占用。例如,最近几天的数据精确到秒,而几个月前的数据精确到天。
- **轮替型数据库(RRD):**以环形缓冲的方式存储固定数量的最新数据,超期数据被轮替覆盖,适用于需要持续监控的场景。
- 查询语言
- **PromQL:**Prometheus 提供的查询语言,支持丰富的查询、聚合和逻辑运算。PromQL 的语法类似于带运算与函数支持的 CSS 选择器。
- **InfluxQL:**InfluxDB 提供的类 SQL 风格的查询语言,支持复杂的查询操作。
- **SQL:**某些时序数据库(如 TimescaleDB)支持标准的 SQL 查询,便于用户使用熟悉的查询语言进行数据分析。
- 实际应用示例
- 假设我们要查询某个网站的访问人数,可以使用 PromQL 进行如下查询:
total_website_visitors{host="icyfenix.cn", job="prometheus"}
- 这条查询语句会返回 `icyfenix.cn` 网站的访问人数,其中 `host` 和 `job` 是标签,用于过滤特定的数据。
(4)监控预警
- 监控预警的目的
- **及时发现系统异常:**通过实时监控系统的关键指标,可以在问题发生初期就及时发现并处理。
- **预防潜在问题:**通过对历史数据的分析,可以预测未来的趋势,从而提前采取措施避免问题发生。
- **提高系统性能:**通过对系统性能指标的监控,可以优化系统配置,提升整体性能。
- **快速故障定位:**在系统出现故障时,可以通过监控数据快速定位问题所在,减少故障恢复时间。
- 监控预警的组成部分
- 客户端指标收集
- 如何定义指标:常见的度量器类型包括:
- **计数度量器(Counter):**累计某个量纲的数值,如销售额、服务调用次数等。
- **瞬态度量器(Gauge):**表示某个指标在某个时点的数值,如当前内存使用量、在线人数等。
- **吞吐率度量器(Meter):**统计单位时间内的吞吐量,如TPS、货运吞吐率等。
- **直方图度量器(Histogram):**记录统计样本及其属性的分布,如GDP变化情况。
- **采样点分位图度量器(Quantile Summary):**评估实际值与理论值的拟合度,如高考成绩分布。
- 如何将这些指标告诉服务端:常见的采集方式包括:
- **拉取式采集(Pull-Based Metrics Collection):**度量系统主动从目标系统中拉取指标。
- **推送式采集(Push-Based Metrics Collection):**目标系统主动向度量系统推送指标。
- 服务端存储查询
- 服务端负责存储和查询度量指标,通常使用时序数据库来存储大量的度量数据。时序数据库的特点包括:
- **数据结构简单:**每个度量指标由时间戳、名称、值和一组标签构成。
- **写多读少:**时序数据通常是追加写入,很少删除或修改。
- **数据保留策略:**可以根据过期时间自动删除相关数据,节省存储空间。
- **数据再采样:**对历史数据进行再采样,以节省存储空间。
- Prometheus 服务端内置了一个强大的时序数据库,并提供了一个名为 PromQL 的数据查询语言,可以对时序数据进行丰富的查询、聚合和逻辑运算。
- 终端监控预警
- **Grafana:**一个开源的度量分析和可视化套件,可以与 Prometheus 等度量系统集成,提供丰富的图表和仪表板。
- **Alert Manager:**Prometheus 提供的专门用于预警的组件,可以根据预设的规则触发预警,并通过多种渠道通知管理员。
- 监控预警的具体实现(以 Prometheus 为例)
- **定义指标:**在目标系统中定义需要收集的度量指标,并使用 Prometheus 的 Client Library 或 Exporter 将指标暴露给 Prometheus。
- **配置采集方式:**选择合适的采集方式(Pull 或 Push),配置 Prometheus Server 从目标系统中拉取或接收指标。
- **存储数据:**Prometheus 服务端将收集到的指标存储在内置的时序数据库中。
- **配置查询:**使用 PromQL 编写查询语句,从时序数据库中提取所需的度量数据。
- **展示数据:**通过 Grafana 等工具将度量数据可视化,生成图表和仪表板。
- **设置预警:**在 Prometheus 中配置 Alert Manager,设置预警规则和通知渠道,当指标达到预设条件时触发预警。
- 监控预警的工具和最佳实践
- 工具:
- **Prometheus:**强大的度量系统,支持多种度量器类型和数据查询语言。
- **Grafana:**开源的度量分析和可视化工具,与 Prometheus 集成度高。
- **Alert Manager:**Prometheus 的预警组件,支持多种通知渠道。
- **Zabbix:**老牌的度量系统,支持多种度量协议。
- 最佳实践:
- **定义关键指标:**选择对系统稳定性影响最大的指标进行监控。
- **合理配置采集频率:**根据系统负载和需求,合理设置采集频率,避免过度采集导致性能下降。
- **使用时序数据库:**选择适合度量数据存储的时序数据库,如 Prometheus 内置的时序数据库。
- **定期审查和优化:**定期审查监控数据和预警规则,优化配置以提高监控效果。
- **多渠道通知:**配置多种通知渠道,确保在紧急情况下能够及时收到预警信息。