gRPC的请求追踪神器go tool trace

简介: gRPC的请求追踪神器go tool trace

gRPC的请求追踪

前言

我们来回顾一下之前分享的知识点:

介绍了基本你的gRPC的使用方式,框架,交互方式等

分享了gRPC的四种认证方式中重要的2种方式,有兴趣可以点击看看哦

整理了openssl 证书的生成,关键点已经高亮标注,值得一看

gRPC生态中的中间件,主要是做统一认证工作,不必要在每一个接口中都写一次认证方式

文章中有分享gRPC的各种功能的中间件,有兴趣可以点击链接,大佬们还请不吝赐教

go tool trace

今天我们来介绍一下go的请求追踪,也就是说go Trace ,分享trace有如下几个原因:

  • 学习完trace之后,你能够自己去实践,清晰的了解整个程序的调用栈
  • 可以通过追踪器捕获大量信息,如图

  • 可以更快的解决我们项目中的疑难杂症

我们或许都有这样的体会,自己思考明白,设计出来的程序,可以很清晰明了的将细节解释明白,对功能的增删改也是可以做到灵活应对。

可是让我们一下子去修改别人写的功能或模块的时候,很多时候会一脸懵逼,这也不敢动,那也不敢动,在不理解的情况下,有疑问,一定要问清楚原理和逻辑,否则搞不好就是线上问题。

如上情况,最重要的一个原因就是自己对当前模块/功能的熟悉程度,以及自己的思维模型是否可迁移。

总而言之,对程序,要有敬畏之心,好奇之心,持之以恒专研下去,要有解决问题的决心。

用go tool trace具体哪些地方合适,哪些地方不合适?

不合适

  • 运行缓慢的函数,或者找到大部分CPU时间花费在哪里,术业有专攻,看CPU时间花费,是有专门的工具的 go tool pprof

合适

  • 找出程序在一段时间内正在做什么
  • go tool trace 可以通过 view trace链接提供的其他可视化功能,对于诊断争用问题帮助极大

开始写一个DEMO

GOMAXPROCS设置可以同时执行的cpu的最大数量,此处我们设置为 1

server.go

package main
import (
   "context"
   "fmt"
   "os"
   "runtime"
   "runtime/trace"
   "sync"
)
func main() {
   // 使用 GOMAXPROCS设置可以同时执行的cpu的最大数量 为 1 个
   runtime.GOMAXPROCS(1)
   f, _ := os.Create("myTrace.dat")
   defer f.Close()
   //开始跟踪,在跟踪时,跟踪将被缓冲并写入 一个我们指定的文件中
   _ = trace.Start(f)
   defer trace.Stop()
   // 咱们自定义一个任务
   ctx, task := trace.NewTask(context.Background(), "customerTask")
   defer task.End()
   var wg sync.WaitGroup
   wg.Add(10)
   for i := 0; i < 10; i++ {
      // 启动10个协程,模拟做任务
      go func(num string) {
         defer wg.Done()
         // 标记  num
         trace.WithRegion(ctx, num, func() {
            var sum, i int64
            // 模拟执行任务
            for ; i < 500000000; i++ {
               sum += i
            }
            fmt.Println(num, sum)
         })
      }(fmt.Sprintf("num_%02d", i))
   }
   wg.Wait()
}

操作步骤:

  • 编译并运行会生成我们既定好的数据文件
  • 通过go tool trace + myTrace.dat
  • 浏览器会弹出traceweb页面,如下

tag 说明
View trace 查看可视化的跟踪情况
Goroutine analysis 协程分析
Network blocking profile (⬇) 网络拥塞情况
Synchronization blocking profile (⬇) 同步阻塞情况
Syscall blocking profile (⬇) 系统调用阻塞情况
Scheduler latency profile (⬇) 调度延迟情况
User-defined tasks 用户自定义的任务
User-defined regions 用户自定义的区域
Minimum mutator utilization 最低 Mutator 利用率

View trace

可视化的web追踪页面

tag 说明
时间线 用于显示执行的时间单元,根据时间维度的不同可以调整区间,可以点击按钮,便可以在界面上拖拽时间线
用于显示执行期间的内存分配和释放情况
协程 用于显示在执行期间的每个 Goroutine 运行阶段有多少个协程在运行,其包含 GC 等待(GCWaiting)、可运行(Runnable)、运行中(Running)这三种状态。
OS 线程 显示在执行期间有多少个线程在运行,其包含正在调用 SyscallInSyscall)、运行中(Running)这两种状态。
虚拟处理器 每个虚拟处理器显示一行,虚拟处理器的数量一般默认为系统内核数。
协程和事件 显示在每个虚拟处理器上有什么 Goroutine 正在运行,而连线行为代表事件关联。

可以使用 shift + ? 唤出帮助手册

点击PROC颜色区域

可以看到该处理器此段时间再做什么事情,如图

tag 说明
Start 开始时间
Wall Duration: 持续时间
Self Time 执行时间
Start Stack Trace 开始时的堆栈信息
End Stack Trace 结束时的堆栈信息
Incoming flow 输入流
Outgoing flow 输出流
Preceding events 之前的事件
Following events 之后的事件
All connected 所有连接的事件

**Event(s)**下方的 Preceding events 点击进去可以看到每一个调用栈的执行时间

用户自定义任务如何查看?

  • User-defined tasks
  • 点击Count
  • goroutine view
  • 点击颜色区域

即可看到此段时间的调用栈,开始时间,结束时间,以及用户定义的任务开了多少个协程等等

User-defined tasks

点击Count

点击goroutine view

点击颜色区域

即可看到此段时间具体在执行什么动作,具体的信息如下

用户自定义区域如何查看呢?

与上述查看用户自定义任务的方式大同小异,如下

  • User-defined regions
  • 点击具体的Count

User-defined regions

点击具体的Count

即可查看到此协程的总共耗时,网络拥塞,同步阻塞,系统调用阻塞,调度等待,垃圾回收扫描,垃圾回收暂停的相关参数信息

那么某一些关键的goroutine被阻止运行时,可能会有延迟问题,大概的原因相信大家应该有些谱了吧

  • 系统调用时被阻塞;
  • 被共享内存阻塞(通道/互斥等)
  • 调度程序没有按照我们所期望的频率运行协程
  • 被runtime系统(例如GC)阻塞

正好上述原因的追踪都可以使用go tool trace 识别到 ,对于我们追踪问题,查询问题原理起了很好的助力作用

好了,本次就到这里,下一次分享 gRPC的HTTP网关

技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。

我是小魔童哪吒,欢迎点赞关注收藏,下次见~


相关文章
|
9月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
10月前
|
Go
如何在Go语言的HTTP请求中设置使用代理服务器
当使用特定的代理时,在某些情况下可能需要认证信息,认证信息可以在代理URL中提供,格式通常是:
672 0
|
12月前
|
Go 开发者 索引
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
496 14
|
缓存 前端开发 中间件
[go 面试] 前端请求到后端API的中间件流程解析
[go 面试] 前端请求到后端API的中间件流程解析
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
JSON 安全 前端开发
类型安全的 Go HTTP 请求
类型安全的 Go HTTP 请求
|
Go
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣437 / 236 )(Go语言版)
本文深入探讨二叉树中路径与祖先问题,涵盖两道经典题目:LeetCode 437(路径总和 III)和236(最近公共祖先)。对于路径总和 III,文章分析了双递归暴力解法与前缀和优化方法,后者通过哈希表记录路径和,将时间复杂度从O(n²)降至O(n)。在最近公共祖先问题中,采用后序遍历递归查找,利用“自底向上”的思路确定最近公共祖先节点。文中详细解析代码实现与核心要点,帮助读者掌握深度追踪技巧,理解树结构中路径与节点关系的本质。这类问题在面试中高频出现,掌握其解法意义重大。
310 4
|
JSON Go API
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
使用Go语言和Gin框架构建RESTful API:GET与POST请求示例
|
监控 中间件 Go
Go 中间件的优雅实现:处理请求的艺术
Go 中间件的优雅实现:处理请求的艺术
|
消息中间件 缓存 Kafka
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)