Skip to content

Commit

Permalink
优化可观测内容
Browse files Browse the repository at this point in the history
  • Loading branch information
isno committed Jan 21, 2025
1 parent 87467e1 commit 043b1eb
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 24 deletions.
10 changes: 5 additions & 5 deletions Observability/dumps.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

核心转储(Core dump)中的 “core” 代表程序的关键运行状态,“dump” 的意思是导出。

核心转储历史悠久,很早就在各类 Unix 系统中出现。在任何安装了《Linux man 手册》的 Linux 发行版上,都可以通过运行 man core 命名查阅相关信息
核心转储历史悠久,很早就在各类 Unix 系统中出现。在任何安装了《Linux man 手册》的 Linux 发行版中,都可以运行 man core 命令查阅相关信息

```bash
$ man core
Expand All @@ -14,12 +14,12 @@ A small number of signals which cause abnormal termination of a process
...
```
上面的大致意思是,当程序异常终止时,Linux 系统会将程序的关键运行状态(如程序计数器、内存映像、堆栈跟踪等)导出到一个“核心文件”(core file)中。工程师使用调试器(如 gdb)打开核心文件,便可查看程序崩溃时的运行状态,更容易定位到问题
上面的大致意思是,当程序异常终止时,Linux 系统会将程序的关键运行状态(如程序计数器、内存映像、堆栈跟踪等)导出到一个“核心文件”(core file)中。工程师通过调试器(如 gdb)打开核心文件,查看程序崩溃时的运行状态,从而帮助定位问题
:::tip 注意
复杂应用程序崩溃时甚至能生成几十 GB 大小的核心文件。默认情况下,核心文件的大小会受到 Linux 系统的限制。如果你想要为特定的程序生成一个无限制大小的核心文件,须通过命令 ulimit -c unlimited,告诉操作系统不要限制核心文件的大小。
复杂应用程序崩溃时,可能会生成几十 GB 大小的核心文件。默认情况下,Linux 系统会限制核心文件的大小。如果你想解除限制,可通过命令 ulimit -c unlimited,告诉操作系统不要限制核心文件的大小。
:::
此外,CNCF 发布的可观测性白皮书中仅提及了 core dump。实际上,dumps 范围应该扩展到 Heap dump(Java 堆栈在特定时刻的快照)、Thread dump(特定时刻的 Java 线程快照)和 Memory dump(内存快照)等等。
值得一提的是,虽然 CNCF 发布的可观测性白皮书仅提到了 core dump。实际上,重要的 dumps 还有 Heap dump(Java 堆栈在特定时刻的快照)、Thread dump(特定时刻的 Java 线程快照)和 Memory dump(内存快照)等等。
虽然 CNCF 将 dumps 纳入可观测性体系,但仍有许多技术难题,如业务容器与操作系统全局配置的冲突、数据持久化的挑战(Pod 重启前需要将数 Gb 的 core dump 文件写入持久卷),导致处理 dumps 数据还得依靠传统手段。
最后,尽管 CNCF 将 dumps 纳入了可观测性体系,但仍有许多技术难题,如容器配置与操作系统全局配置的冲突、数据持久化的挑战(Pod 重启前将数 Gb 的 core 文件写入持久卷)等等,导致处理 dumps 数据还得依靠传统手段。
33 changes: 15 additions & 18 deletions Observability/profiles.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
# 9.3.4 性能剖析 Profiling

熟悉 Golang 的工程师对 pprof 工具一定不陌生。借助 pprof 提供的 CPU 和内存分析功能,工程师能够深入了解 Golang 函数的执行时间、内存使用情况,从而优化应用性能。
熟悉 Golang 的工程师对 pprof 工具一定不陌生。借助 pprof 提供的 CPU 和内存分析功能,我们能够深入了解 Golang 程序的执行时间、内存使用情况,从而优化应用性能。

可观测性领域内的性能剖析(Profiling) Golang 中的 pprof 目标一致,两者皆是对运行中应用进行分析、生成详细的运行数据(Profiles),帮助工程师全面了解应用运行时的行为、资源使用全貌,从而确定代码和性能瓶颈之间的关联
可观测性领域的性能剖析(Profiling) Golang 中的 pprof 工具目标相同,二者都旨在对运行中的应用进行分析,生成详细的性能数据(Profiles),帮助工程师全面了解应用的运行行为和资源使用情况,从而识别代码中的性能瓶颈

Profiles 数据通常以火焰图、堆栈图形式呈现,分析它们是从“是什么”到“为什么”这一过程中重要环节。例如,通过链路追踪识别出延迟(是什么)的位置,然后根据火焰图进一步定位到具体的代码行(为什么)。2021 年,国内某网站崩溃,工程师分析火焰图发现 Lua 代码存在异常,最终定位到问题源头[^1]
性能数据通常以火焰图或堆栈图的形式呈现,分析这些数据是从“是什么”到“为什么”过程中的关键环节。例如,通过链路追踪识别延迟源(是什么),然后根据火焰图进一步分析,定位到具体的代码行(为什么)。2021 年,某网站发生崩溃事件,工程师通过分析火焰图发现 Lua 代码存在异常,最终定位到问题源头[^1]

:::center
![](../assets/lua-cpu-flame-graph.webp)<br/>
图 9-16 Lua 代码的 CPU 火焰图
图 9-16 Lua 代码的 CPU 火焰图(由于函数调用按层叠加,火焰图呈现出类似火焰的形状)
:::

:::tip 火焰图分析说明

火焰图颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。

- 纵轴表示调用堆栈深度,越往上表示调用链越深,调用顺序依次向上。最底层的横向条形表示最开始的调用(通常是主函数或入口函数),每一层之上的条形表示被下层函数调用的函数。
- 横轴表示某个函数在采样期间占用的时间比例(宽度越大,表示消耗时间越长)。

分析火焰图的关键是观察横向条形的宽度,宽度越大表示该函数占用的时间越多。一旦出现“平顶”,则可能意味着该函数存在性能瓶颈。
- 纵轴:表示函数调用的堆栈深度(或层级)。纵向越高表示调用链越深,底部通常是程序的入口函数(如 main 函数),上层是被下层函数调用的函数。
- 横轴:表示函数在特定时间段内所占用的 CPU 时间或内存空间,条形的宽度越大,表示该函数消耗的时间或资源越多。

分析火焰图的关键是观察横向条形的宽度,宽度越大,函数占用的时间越多。如果某个函数的条形图出现“平顶”现象,表示该函数的执行时间过长,可能成为性能瓶颈。
:::

Profiles 数据包括多种类型,由不同的分析器(Profiler)生成,常见分析器如下
性能数据有多种类型,每种类型由不同的分析器(Profiler)生成,常见的分析器包括

- **CPU 分析器**:跟踪程序中每个函数或代码块的运行时间,记录函数调用的堆栈信息,生成调用图,显示函数之间的调用关系和时间分布。工程师利用调用图,可以找出 CPU 使用率最高的代码段,集中优化这些“热点”部分
- **堆分析器(Heap Profiler)**:监控程序的内存使用情况,帮助定位内存泄漏或不必要的内存分配。例如,Java 应用中,使用 Heap Profiler 定位导致内存溢出的具体对象
- **GPU 分析器**:分析 GPU 的使用情况,常见于游戏开发或其他图形密集型应用场景,用于优化渲染性能
- **互斥锁分析器**:检测程序中互斥锁的竞争情况,帮助优化线程间的并发性能,减少因锁争用导致的性能瓶颈
- **I/O 分析器**:评估 I/O 操作的性能,包括文件读写延迟和网络请求耗时,帮助识别数据传输瓶颈并提升效率
- **特定编程语言的分析器**:例如 JVM Profiler,专门分析运行在 Java 虚拟机上的应用程序,挖掘与语言特性相关的性能问题
- **CPU 分析器**:跟踪程序中每个函数或代码块的运行时间,记录函数调用堆栈信息,生成调用图,并展示函数之间的调用关系和时间分布
- **堆分析器(Heap Profiler)**:监控程序的内存使用情况,帮助定位内存泄漏或不必要的内存分配。例如,Java 工程师通过堆分析器定位导致内存溢出的具体对象
- **GPU 分析器**:分析 GPU 的使用情况,主要用于图形密集型应用(如游戏开发),优化渲染性能
- **互斥锁分析器**:检测程序中互斥锁的竞争情况,帮助优化线程间的并发性能,减少锁争用引发的性能瓶颈
- **I/O 分析器**:评估 I/O 操作的性能,包括文件读写延迟和网络请求耗时,帮助识别数据传输瓶颈并提高效率
- **特定编程语言分析器**:例如 JVM Profiler,用于分析在 Java 虚拟机上运行的应用程序,挖掘与编程语言特性相关的性能问题

过去,分析器资源消耗较高,工程师通常仅在紧急情况下临时启用它们。随着低开销分析技术的兴起,如编程语言层面的 Java Flight Recorder 和 Async Profiler 技术、操作系统层面的 systemTap 和 eBPF 技术,生产环境中进行“持续性能分析”(Continuous Profiling)逐渐成为可能,捕获线上“疑难杂症”的现场快照也变得更加容易
过去,由于分析器资源消耗较高,通常仅在紧急情况下启用。随着低开销分析技术的发展,如编程语言层面的 Java Flight Recorder 和 Async Profiler 技术、操作系统层面的 systemTap 和 eBPF 技术的出现,让在生产环境进行持续性能分析(Continuous Profiling)成为可能,解决线上“疑难杂症”也变得更加容易

[^1]: 参见《2021.07.13 我们是这样崩的》https://www.bilibili.com/read/cv17521097/

2 changes: 1 addition & 1 deletion Observability/summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ given enough eyeballs, all bugs are shallow.

随着系统规模扩大、组件复杂化以及服务间依赖关系的增加,确保系统稳定性已超出绝大多数 IT 团队的能力极限。

复杂性失控问题在工业领域同样出现过。19 世纪末起,电气工程的细分领域迅速发展,尤其是 20 世纪 50 年代的航空领域,研发效率要求越来越高、运行环境越来越多样化,系统日益复杂对稳定性提出了巨大挑战。在这一背景下,匈牙利裔工程师 Rudolf Emil Kálmán 提出了“可观测性”概念,其理念的核心是“通过系统外部的输出信号,判断工作状态并定位缺陷的根因”。
复杂性失控问题在工业领域同样出现过。19 世纪末起,电气工程的细分领域迅速发展,尤其是 20 世纪 50 年代的航空领域,研发效率要求越来越高、运行环境越来越多样化,系统日益复杂对稳定性提出了巨大挑战。在这一背景下,匈牙利裔工程师 Rudolf Emil Kálmán 提出了“可观测性”概念,其理念的核心是“通过分析系统向外部输出的信号,判断工作状态并定位缺陷的根因”。

借鉴电气系统的观测理念,我们也可以通过系统输出各类信息,实现软件系统的可观测性。2018 年,CNCF 率先将“可观测性”概念引入 IT 领域,强调它是云原生时代的必备能力!从生产所需到概念发声,加之 Google 在内的众多大厂一拥而上,“可观测性”逐渐取代“监控”,成为云原生领域最热门的话题之一。

Expand Down

0 comments on commit 043b1eb

Please sign in to comment.