From 3711b12fad80c28aef9fc32953934b15c22b8581 Mon Sep 17 00:00:00 2001 From: xfy Date: Wed, 8 Apr 2026 13:24:31 +0800 Subject: [PATCH] =?UTF-8?q?docs(server/pprof):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E8=AF=A6=E7=BB=86=E5=87=BD=E6=95=B0=E6=96=87=E6=A1=A3=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=EF=BC=8C=E4=BF=AE=E5=A4=8D=E6=B3=A8=E9=87=8A=E9=94=99?= =?UTF-8?q?=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 pprof.go 和 pprof_impl.go 的所有公开函数添加文档注释 - 包含参数说明、返回值描述、使用示例和注意事项 - 修复注释错字"厉止"→"停止" - 补充包级文档说明核心功能和用途 Co-Authored-By: Claude --- internal/server/pprof.go | 64 +++++++++++++++++++++++++++++- internal/server/pprof_impl.go | 74 ++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 3 deletions(-) diff --git a/internal/server/pprof.go b/internal/server/pprof.go index d5ed468..a76b74e 100644 --- a/internal/server/pprof.go +++ b/internal/server/pprof.go @@ -7,10 +7,15 @@ // - 阻塞分析 // - 锁竞争分析 // +// 主要用途: +// +// 用于在生产环境中采集性能数据,支持性能优化和问题排查。 +// // 注意事项: // - 仅在配置启用时生效 // - 生产环境建议限制访问 IP // - CPU profile 收集需要代表性 workload +// - 所有端点均支持流式输出,适合大数据量场景 // // 作者:xfy package server @@ -85,6 +90,16 @@ func NewPprofHandler(cfg *config.PprofConfig) (*PprofHandler, error) { } // Path 返回 pprof 端点路径。 +// +// 返回配置的 pprof 端点路径前缀,用于路由注册。 +// +// 返回值: +// - string: pprof 端点的路径前缀,如 "/debug/pprof" +// +// 使用示例: +// +// path := handler.Path() +// router.GET(path, handler.ServeHTTP) func (h *PprofHandler) Path() string { return h.path } @@ -93,6 +108,13 @@ func (h *PprofHandler) Path() string { // // 根据 URL 路径选择对应的 profile 处理器, // 并检查客户端 IP 是否在允许列表中。 +// +// 参数: +// - ctx: fasthttp 请求上下文,包含请求信息和响应写入接口 +// +// 注意事项: +// - 未授权访问返回 403 Forbidden +// - 未知的 profile 类型返回 404 Not Found func (h *PprofHandler) ServeHTTP(ctx *fasthttp.RequestCtx) { // IP 访问控制 if !h.isAllowed(ctx) { @@ -125,6 +147,15 @@ func (h *PprofHandler) ServeHTTP(ctx *fasthttp.RequestCtx) { } // isAllowed 检查客户端 IP 是否允许访问。 +// +// 根据配置的 IP 白名单和 CIDR 网络范围验证客户端 IP。 +// 若未配置任何限制,则默认允许所有访问。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于获取客户端 IP +// +// 返回值: +// - bool: true 表示允许访问,false 表示禁止访问 func (h *PprofHandler) isAllowed(ctx *fasthttp.RequestCtx) bool { if len(h.allowedIPs) == 0 && len(h.allowedNets) == 0 { return true // 无限制 @@ -154,6 +185,11 @@ func (h *PprofHandler) isAllowed(ctx *fasthttp.RequestCtx) bool { } // handleIndex 处理索引页面。 +// +// 返回 HTML 格式的 pprof 端点索引页面,列出所有可用的 profile 类型。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于写入响应内容 func (h *PprofHandler) handleIndex(ctx *fasthttp.RequestCtx) { ctx.SetContentType("text/html; charset=utf-8") html := ` @@ -174,6 +210,12 @@ func (h *PprofHandler) handleIndex(ctx *fasthttp.RequestCtx) { } // handleCPU 处理 CPU profile 请求。 +// +// 启动 CPU profile 采集,等待指定时长后停止并返回结果。 +// 采集时长可通过 URL 参数 "seconds" 指定,默认 30 秒。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于获取参数和写入响应 func (h *PprofHandler) handleCPU(ctx *fasthttp.RequestCtx) { // 获取采集时长 seconds := 30 @@ -195,13 +237,18 @@ func (h *PprofHandler) handleCPU(ctx *fasthttp.RequestCtx) { // 等待采集完成 time.Sleep(time.Duration(seconds) * time.Second) - // 厉止 CPU profile + // 停止 CPU profile stopCPUProfile() _ = w.Flush() }) } // handleHeap 处理内存 profile 请求。 +// +// 执行 GC 后采集内存分配 profile 并返回结果。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于写入响应 func (h *PprofHandler) handleHeap(ctx *fasthttp.RequestCtx) { ctx.SetContentType("application/octet-stream") ctx.SetBodyStreamWriter(func(w *bufio.Writer) { @@ -211,6 +258,11 @@ func (h *PprofHandler) handleHeap(ctx *fasthttp.RequestCtx) { } // handleGoroutine 处理 Goroutine profile 请求。 +// +// 采集当前所有 Goroutine 的栈追踪信息并返回。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于写入响应 func (h *PprofHandler) handleGoroutine(ctx *fasthttp.RequestCtx) { ctx.SetContentType("application/octet-stream") ctx.SetBodyStreamWriter(func(w *bufio.Writer) { @@ -220,6 +272,11 @@ func (h *PprofHandler) handleGoroutine(ctx *fasthttp.RequestCtx) { } // handleBlock 处理阻塞 profile 请求。 +// +// 采集阻塞操作的 profile 数据并返回。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于写入响应 func (h *PprofHandler) handleBlock(ctx *fasthttp.RequestCtx) { ctx.SetContentType("application/octet-stream") ctx.SetBodyStreamWriter(func(w *bufio.Writer) { @@ -229,6 +286,11 @@ func (h *PprofHandler) handleBlock(ctx *fasthttp.RequestCtx) { } // handleMutex 处理锁竞争 profile 请求。 +// +// 采集互斥锁竞争的 profile 数据并返回。 +// +// 参数: +// - ctx: fasthttp 请求上下文,用于写入响应 func (h *PprofHandler) handleMutex(ctx *fasthttp.RequestCtx) { ctx.SetContentType("application/octet-stream") ctx.SetBodyStreamWriter(func(w *bufio.Writer) { diff --git a/internal/server/pprof_impl.go b/internal/server/pprof_impl.go index 99a5702..3fe4cba 100644 --- a/internal/server/pprof_impl.go +++ b/internal/server/pprof_impl.go @@ -1,6 +1,19 @@ // Package server 提供 pprof 性能分析的底层实现。 // // 该文件封装 runtime/pprof 的调用,为 fasthttp 提供流式输出支持。 +// 包含以下核心功能: +// - CPU profile 的启动和停止 +// - 内存分配 profile 的写入 +// - Goroutine stack traces 的写入 +// - 阻塞和锁竞争 profile 的写入 +// +// 主要用途: +// +// 作为 pprof.go 的底层实现层,处理与 runtime/pprof 的直接交互。 +// +// 注意事项: +// - CPU profile 使用互斥锁保护,确保并发安全 +// - 所有写入操作均使用 io.Writer 接口,支持流式输出 // // 作者:xfy package server @@ -14,7 +27,16 @@ import ( ) var ( - cpuProfileMu sync.Mutex + // cpuProfileMu 保护 cpuProfileActive 状态的互斥锁。 + // + // 用于确保 CPU profiling 启动和停止操作的线程安全性, + // 防止并发调用 startCPUProfile/stopCPUProfile 导致的状态不一致。 + cpuProfileMu sync.Mutex + + // cpuProfileActive 标记当前 CPU profile 是否处于采集状态。 + // + // 值为 true 表示正在采集,false 表示未采集。 + // 该变量由 cpuProfileMu 保护,不应直接访问。 cpuProfileActive bool ) @@ -41,7 +63,13 @@ func startCPUProfile(w io.Writer) error { return nil } -// stopCPUProfile 厉止 CPU profile 采集。 +// stopCPUProfile 停止 CPU profile 采集。 +// +// 终止正在进行的 CPU profile 采集,并将缓冲数据刷新到输出。 +// 若当前无活跃采集,则忽略该调用。 +// +// 注意事项: +// - 该函数由 cpuProfileMu 保护,调用前无需额外加锁 func stopCPUProfile() { cpuProfileMu.Lock() defer cpuProfileMu.Unlock() @@ -53,12 +81,23 @@ func stopCPUProfile() { } // writeHeapProfile 写入内存分配 profile。 +// +// 执行 GC 后采集内存分配数据并写入输出流。 +// GC 可确保获取更准确的内存使用数据。 +// +// 参数: +// - w: 输出 writer,用于写入 profile 数据 func writeHeapProfile(w io.Writer) { runtime.GC() // 先执行 GC,获取更准确的数据 _ = pprof.WriteHeapProfile(w) } // writeGoroutineProfile 写入 Goroutine stack traces。 +// +// 采集当前所有 Goroutine 的栈追踪信息并写入输出流。 +// +// 参数: +// - w: 输出 writer,用于写入 profile 数据 func writeGoroutineProfile(w io.Writer) { p := pprof.Lookup("goroutine") if p != nil { @@ -67,6 +106,11 @@ func writeGoroutineProfile(w io.Writer) { } // writeBlockProfile 写入阻塞 profile。 +// +// 采集阻塞操作的 profile 数据并写入输出流。 +// +// 参数: +// - w: 输出 writer,用于写入 profile 数据 func writeBlockProfile(w io.Writer) { p := pprof.Lookup("block") if p != nil { @@ -75,6 +119,11 @@ func writeBlockProfile(w io.Writer) { } // writeMutexProfile 写入锁竞争 profile。 +// +// 采集互斥锁竞争的 profile 数据并写入输出流。 +// +// 参数: +// - w: 输出 writer,用于写入 profile 数据 func writeMutexProfile(w io.Writer) { p := pprof.Lookup("mutex") if p != nil { @@ -83,10 +132,22 @@ func writeMutexProfile(w io.Writer) { } // bufioWriterAdapter 将 bufio.Writer 包装为 io.Writer,自动 Flush。 +// +// 该结构体实现 io.Writer 接口,在每次写入后自动调用 Flush, +// 确保数据立即发送到客户端,适用于流式响应场景。 type bufioWriterAdapter struct { + // w 被包装的 bufio.Writer w *bufio.Writer } +// Write 实现 io.Writer 接口,写入数据并自动 Flush。 +// +// 参数: +// - p: 待写入的字节切片 +// +// 返回值: +// - n: 实际写入的字节数 +// - err: 写入过程中遇到的错误 func (a *bufioWriterAdapter) Write(p []byte) (n int, err error) { n, err = a.w.Write(p) if err == nil { @@ -96,6 +157,15 @@ func (a *bufioWriterAdapter) Write(p []byte) (n int, err error) { } // wrapBufioWriter 将 bufio.Writer 包装为 io.Writer。 +// +// 创建一个 bufioWriterAdapter 实例,使 bufio.Writer 能够 +// 在每次写入后自动 Flush,满足流式输出的需求。 +// +// 参数: +// - w: 待包装的 bufio.Writer +// +// 返回值: +// - io.Writer: 包装后的 io.Writer 接口实例 func wrapBufioWriter(w *bufio.Writer) io.Writer { return &bufioWriterAdapter{w: w} }