文|Junlong Liu

Shopee Digital Purchase & Local Services Engineering

本文1743字 阅读 6分钟

贡献者前言

我是在开发工作过程中了解到 Holmes 的,为了保障体系稳定性需求一个功用排查东西,因而也需求一个保存现场的功用监控东西。当我在网上查询该方面的开源库时,发现可用的并不多。后续找到 MOSN 社区的 Holmes ,发现这个开源库功用根本完全、扩展性也高,特别是 GCHeapDump 这个业界抢先的功用,对处理内存升高的问题非常有用。

2021 年年末了解到的 Holmes 组件,然后开端了解 Holmes 所在的 MOSN 社区。Holmes 作为功用排查东西,中心功用是及时发现功用目标反常,并对体系进行 Profiling。

因为 Holmes 还处于萌芽期,除了 Readme 之外的文档资料并不多。还有一些 Holmes 其时不支撑的功用,比如动态装备调整与上报。Holmes 其时也还没发布第一个版本,可是自己对这方面也有兴趣和理解,于是在 GitHub 上提了几个 Issue 评论,社区回复的速度非常快。后续在社区长辈们的辅导下提了 PR,也因而经过 Holmes 的代码规划学习到了很多关于开源组件的规划理念。

因而我决议参加开源社区并贡献代码,以处理实践需求。有了一定的了解和经验之后,经过和人德长辈评论,总结这样一篇共享文章。

本文将介绍 Holmes 的运用场景、快速开端事例、多个监控类型、规划原理、扩展功用与怎么凭借 Holmes 搭建起一套简略的功用排查体系,欢迎我们留言辅导。

Holmes 运用场景

关于体系的功用尖刺问题,咱们通常运用 Go 官方内置的 pprof 包进行剖析,可是难点是关于一闪而过的“尖刺”,开发人员很难及时保存现场:当你收到告警信息,从被窝中爬起来,翻开电脑链接 VPN,体系说不定都现已重启三四趟了。

MOSN 社区的 Holmes 是一个依据 Golang 完成的轻量级功用监控体系,当运用的功用目标发生了反常动摇时,Holmes 会在第一时刻保存现场,让你第二天上班能够一边从容地喝着枸杞茶,一边追查问题的根因。

Quick Start

运用 Holmes 的办法非常简略,只需求在您的体系初始化逻辑内添加以下代码:

 // 装备规矩
    h, _ := holmes.New(
        holmes.WithCollectInterval("5s"), // 目标收集时刻间隔
        holmes.WithDumpPath("/tmp"),      // profile保存路径
        holmes.WithCPUDump(10, 25, 80, 2 * time.Minute),  // 装备CPU的功用监控规矩
        holmes.WithMemDump(30, 25, 80, 2 * time.Minute),// 装备Heap Memory 功用监控规矩
        holmes.WithGCHeapDump(10, 20, 40, 2 * time.Minute), // 装备依据GC周期的Heap Memory 功用监控规矩
        holmes.WithGoroutineDump(500, 25, 20000, 100*1000, 2 * time.Minute),    //装备Goroutine数量的监控规矩
    )
    // enable all
    h.EnableCPUDump().
    EnableGoroutineDump().
  EnableMemDump().
  EnableGCHeapDump().Start()

类似于 holmes.WithGoroutineDump(min, diff, abs,max,2 * time.Minute) 的 API 意义为:

当 Goroutine 目标满足以下条件时,将会触发 Dump 操作。

当 Goroutine 数大于 Max 时,Holmes 会越过本次 Dump 操作,因为当 Goroutine 数过大时,Goroutine Dump 操作成本很高。

2 * time.Minute 是两次 Dump 操作之间最小时刻间隔,避免频频 Profiling 对功用发生的影响。

更多运用事例见文末的 Holmes 运用事例文档。

Profile Types

Holmes 支撑以下五种 Profile 类型,用户能够按需装备。

Mem: 内存分配

CPU: CPU 运用率

Thread: 线程数

Goroutine: 协程数

GCHeap: 依据 GC 周期监控的内存分配

目标收集

Mem、CPU、Thread、Goroutine 这四种类型是依据用户装备的 CollectInterval,每隔一段时刻收集一次运用当时的功用目标,而 gcHeap 时依据 GC 周期收集功用目标。

本小节会剖析一下两种目标。

依据 CollectInterval 周期收集

Holmes 每隔一段时刻收集运用各项目标,并运用一个固定巨细的循环链表来存储它们。

社区文章|MOSN 社区性能分析利器——Holmes 原理浅析

依据 GC 周期收集

在一些场景下,咱们无法经过定时的 memory dump 保存到现场。比如运用在一个 CollectInterval 周期内分配了很多内存,又快速回收了它们。此刻 Holmes 在周期前后的收集到内存运用率没有发生过大动摇,与实践状况不符。

为了处理这种状况,Holmes 开发了依据 GC 周期的 Profile 类型,它会在堆内存运用率飙高的前后两个 GC 周期内各 Dump 一次 Profile,然后开发人员能够运用 pprof –base 命令去比照两个时刻堆内存之间的差异。

依据 GC 周期收集到的数据也会放在循环列表中。

规矩判别

本小节介绍 Holmes 是怎么依据规矩判别体系出现反常的。

阈值意义

每个 Profile 都能够装备 min、diff、abs、coolDown 四个目标,意义如下:

当时目标小于 min 时,不视为反常。

当时目标大于 (100+diff)100% 前史目标,说明体系此刻发生了动摇,视为反常。

当时目标大于 abs (绝对值)时,视为反常。

CPU 和 Goroutine 这两个 Profile 类型提供 Max 参数装备,依据以下考虑:

CPU 的 Profiling 操作大约会有 5% 的功用损耗,所以当在 CPU 过高时,不应当进行 Profiling 操作,否则会拖垮体系。

当 Goroutine 数过大时,Goroutine Dump 操作成本很高,会进行 STW 操作,然后拖垮体系。(概况见文末参考文章)

Warming up

当 Holmes 启动时,会依据 CollectInterval 周期收集十次各项目标,在这期间内收集到的目标只会存入循环链表中,不会进行规矩判别。

扩展功用

除了根本的监控之外,Holmes 还提供了一些扩展功用:

事件上报

您能够经过完成 Reporter 来完成以下功用:

发送告警信息,当 Holmes 触发 Dump 操作时。

将 Profiles 上传到其他地方,以防实例被毁掉,然后导致 Profile 丢掉,或进行剖析。

  type ReporterImpl struct{}
        func (r *ReporterImple) Report(pType string, buf []byte, reason string, eventID string) error{
            // do something  
        }
        ......
        r := &ReporterImpl{} // a implement of holmes.ProfileReporter Interface.
      h, _ := holmes.New(
            holmes.WithProfileReporter(reporter),
            holmes.WithDumpPath("/tmp"),
            holmes.WithLogger(holmes.NewFileLog("/tmp/holmes.log", mlog.INFO)),
            holmes.WithBinaryDump(),
            holmes.WithMemoryLimit(100*1024*1024), // 100MB
            holmes.WithGCHeapDump(10, 20, 40, time.Minute),
)

动态装备

您能够经过 Set 办法在运用运行时更新 Holmes 的装备。它的运用非常简略,和初始化时的 New 办法一样。

有些装备时不支撑动态更改的,比如 Core 数。如果在体系运行期间更改这个参数,会导致 CPU 运用率发生巨大动摇,然后触发 Dump 操作。

h.Set(
        WithCollectInterval("2s"),
        WithGoroutineDump(10, 10, 50, 90, time.Minute))

落地事例

运用 Holmes 的 Set 办法,能够轻松地对接自己公司的装备中心,比如,将 Holmes 作为数据面,装备中心作为控制面。并对接告警体系(邮件/短信等)搭建一套简略的监控体系。

具体架构如下:

社区文章|MOSN 社区性能分析利器——Holmes 原理浅析

Holmes V1.0 版本发布

本文简略地介绍了 Holmes 的运用办法与原理。期望 Holmes 能在您进步运用的稳定性时协助到你。

Holmes V1.0 在几周前正式发布了,作为贡献者和运用者,我非常引荐我们试用这个小巧的东西库,有任何问题和疑问欢迎我们来社区发问~

Holmes 是 MOSN 社区开源的 GO 言语 Continous Profiling 组件,能够主动发现 CPU、 Memory、Goroutine 等资源的反常,并主动 Dump 反常现场 Profile,用于过后剖析定位。也支撑上传 Profile 到主动剖析平台,完成主动问题确诊、报警。

「发布陈述」:github.com/mosn/holmes…

「Holmes 原理介绍」:mosn.io/blog/posts/…

本文简略地介绍了 Holmes 的运用办法与原理。期望 Holmes 能在您进步运用的稳定性时协助到你。

「参考资料」

[1]《Holmes 文档》github.com/mosn/holmes

[2]《无人值守的主动 dump(一)》xargin.com/autodumper-…

[3]《无人值守的主动 dump(二)》xargin.com/autodumper-…

[4]《go 言语 pprof heap profile 完成机制》uncledou.site/2022/go-ppr…

[5]《goroutines pprofiling STW》github.com/golang/go/i…

[6]《Holmes 运用事例文档》github.com/mosn/holmes…

[7]《go pprof 功用损耗》medium.com/google-clou…

本周引荐阅读

邀请函|SOFA 四周年,开源正其时!

Nydus 镜像加快插件迁入 Containerd 旗下

异构注册中心机制在中国工商银行的探索实践

SOFAArk Committer 专访|看它不爽,就直接着手改!