首页 > 其他分享 >golang 运行时死锁排查和检测

golang 运行时死锁排查和检测

时间:2024-03-20 15:58:52浏览次数:24  
标签:github berkaroad detectlock golang 排查 死锁 file go main

当运行的系统发生goroutine等待获取锁时间超过预期时,判定为发生了死锁。因目前代码中使用了一些公开的锁实例,调用链也比较长,对问题排查带来了很大困扰。为了便于问题排查,需要借助工具来实现。

1. 发生死锁的判定依据和原因

1.1 判定依据

如下为使用Mutex锁产生的锁等待,并持续了222分钟。这类不合理现象,就判定为发生了死锁。(以下为cpu-pprof导出的stack信息)

goroutine 61508 [semacquire, 222 minutes]:
sync.runtime_SemacquireMutex(0xc00048f564, 0x4f4300, 0x1)
    /opt/go/src/runtime/sema.go:71 +0x47
sync.(*Mutex).lockSlow(0xc00048f560)
    /opt/go/src/sync/mutex.go:138 +0x105
sync.(*Mutex).Lock(...)
    /opt/go/src/sync/mutex.go:81
......

1.2 产生死锁的原因

  • 锁重入

  • 多把锁加锁,并发访问时加锁顺序不一致

  • 锁未释放

2. 死锁问题诊断

常用的标准库锁: sync.Mutex, sync.RWMutex,目标暂定为以检测这两类锁的死锁问题。

检测死锁的方法:分为静态代码分析、运行期分析。

2.1 静态代码分析

  • 优势:

    可以做到场景全覆盖。

  • 劣势:

    好像没有劣势,但开发难度较高,目前发现的一个开源工具 go-tools,验证下来无法检测互锁问题,但可以检测锁未释放的问题。

2.2 运行期分析

  • 优势:

    可以快速定位问题,检测相对容易。

  • 劣势:

    对代码有侵入性,需要封装标准库的锁,对性能会有一定影响,应采取条件编译方式,生产环境勿启用。

3. 运行期分析工具开发

3.1 目标

  • 支持 Mutex 和 RWMutex

  • 支持锁重入、互锁问题的检测

3.2 用法

import (
    "github.com/berkaroad/detectlock-go"
)

// 应用启动时,设置启用调试
detectlock.EnableDebug()

// 声明 sync.Mutex、sync.RWMutex 替换为 detectlock.Mutex、detectlock.RWMutex
var locker1 *detectlock.Mutex = &detectlock.Mutex{}
var locker2 *detectlock.RWMutex = &detectlock.RWMutex{}

// 异步检测死锁
items := detectlock.Items()
fmt.Println(detectlock.DetectAcquired(items)) // 检测获得锁的goroutine列表
fmt.Println(detectlock.DetectReentry(items)) // 检测锁重入的goroutine列表
fmt.Println(detectlock.DetectLockedEachOther(items)) // 检测互锁的goroutine列表

// 关闭调试,并清理锁使用信息
detectlock.DisableDebug()

3.3 死锁示例数据

  • 检测 sync.Mutex 多把锁顺序不一致导致的互锁
--- DetectAcquired ---
goroutine 29: [(0xc0000b4008, acquired, main.B (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:30)), (0xc0000b4000, wait, main.B (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:33))]
goroutine 30: [(0xc0000b4000, acquired, main.A (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:20)), (0xc0000b4008, wait, main.A (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:23))]

--- DetectLockedEachOther ---
goroutine 29: [(0xc0000b4008, acquired, main.B (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:30)), (0xc0000b4000, wait, main.B (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:33))]
goroutine 30: [(0xc0000b4000, acquired, main.A (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:20)), (0xc0000b4008, wait, main.A (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex01/main.go:23))]

  • 检测 sync.Mutex 锁重入
--- DetectAcquired ---
goroutine 53: [(0xc0000160b8, acquired, main.C (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex02/main.go:19)), (0xc0000160b8, wait, main.C (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex02/main.go:22))]

--- DetectReentry ---
goroutine 53: [(0xc0000160b8, acquired, main.C (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex02/main.go:19)), (0xc0000160b8, wait, main.C (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex02/main.go:22))]

  • 检测 sync.Mutex、sync.RWMutex 多把锁顺序不一致导致的互锁
--- DetectAcquired ---
goroutine 8: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 10: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 13: [(0xc0000160b8, acquired, main.E (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:30)), (0xc0000180c0, wait, main.E (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:33))]
goroutine 14: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 16: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 50: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 52: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 54: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 56: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 58: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]

--- DetectLockedEachOther ---
goroutine 8: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 10: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 13: [(0xc0000160b8, acquired, main.E (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:30)), (0xc0000180c0, wait, main.E (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:33))]
goroutine 14: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 16: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 50: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 52: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 54: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 56: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]
goroutine 58: [(0xc0000180c0, r-acquired, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:21)), (0xc0000160b8, wait, main.D (file: /home/berkaroad/github/berkaroad/detectlock-go/examples/mutex03/main.go:24))]

---------------------------------分割线-------------------------------------------------------------

我的detectlock-go项目: https://github.com/berkaroad/detectlock-go,已经挂在github上,有兴趣的可以去了解下。

使用中有何问题,欢迎在github上给我提issue,谢谢!

标签:github,berkaroad,detectlock,golang,排查,死锁,file,go,main
From: https://www.cnblogs.com/Berkaroad/p/18085400

相关文章

  • Html2canvas——图片空白的几种排查解决方案
    问题:用html2canvas生成画布图片,再转成pdf。生成图片时内容结构里的图片显示空白。解决:首先服务器设置图片允许跨域,如阿里云腾讯云配置跨域规则。其次图片设置crossOrigin=“anonymous”,并且拿到图片地址加随机参数如src+‘?v=’+Math.random()防止使用缓存,再者html2canvas......
  • golang实现数据分组
    背景:从数据库里查出了532条数据,这532条数据需要通过一个接口过滤符合条件的,由于过滤比较流程长,过滤接口避免超时,只允许一次请求100条,于是我们就需要针对这个532条数据进行分组。思路:就是把这个数据分成6组,前5组是100条,第6组是32条。max=532/100取整,532%100不等于零max+1,创建一个......
  • nicelog--强大的Java日志组件,排查问题的利器
    ​ nicelog是一个功能强大的Java日志组件,它可以自动、手动收集日志,并通过traceId将日志关联起来,可极大提高排查问题的速度。官网:https://www.yuque.com/knifeblade/opensource/niceloggitee:https://gitee.com/knifeedge/niceloggithub:https://github.com/knife-blade/nicelog......
  • GB28181视频汇聚平台EasyCVR接入Ehome设备,设备在线但视频无法播放的原因排查
    安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安防视频监控的能力,也具备接入AI智能分析的......
  • golang sync.Map之如何设计一个并发安全的读写分离结构?
    在golang中,想要并发安全的操作map,可以使用sync.Map结构,sync.Map是一个适合读多写少的数据结构,今天我们来看看它的设计思想,来看看为什么说它适合读多写少的场景。如下,是golang中sync.Map的数据结构,其中属性read是只读的map,dirty是负责写入的map,sync.Map中的键值对value......
  • mysql查看数据库锁等待排查笔记
    实验版本:5.7.27 命令如下:mysql>useinformation_schema;  mysql>selectcount(*)fromINNODB_LOCK_WAITS; +----------+ |count(*)| +----------+ |      50| +----------+ 1rowinset,1warning(0.00sec)  SHOWENGINEINNODB......
  • Golang案例开发之gopacket监听网卡抓包(2)
    文章目录前言二、实践监听网卡抓包1.代码2.知识点OpenLive方法SetBPFFilter断言总结前言本节实战,监听指定网卡,进行网络抓包,根据分层,解析不同分层包的内容。二、实践监听网卡抓包1.代码代码如下(示例):packagemainimport( "fmt" "log" "......
  • 第七章 Windows 10常见故障排查_实验案例一
    实验案例一:使用Windows安全模式解决系统故障1、实验环境    某公司的计算机全部安装了Windows10操作系统.公司员工由于操作不当,误安装了错误的驱动程序.导致计算机无法正常启动,现需要将错误的驱动程序卸载.2、需求描述通过安全模式进入操作系统。卸载掉存在兼容性......
  • Windows 10常见故障排查_实验案例(一)
    实验案例一:使用Windows安全模式解决系统故障1、实验环境    某公司的计算机全部安装了Windows10操作系统,公司员工由于操作不当,误安装了错误的驱动程。导致计算机无法正常启动,现需要将错误的驱动程序卸载。2、需求描述通过安全模式进入操作系统。卸载掉存在兼容性......
  • 第七章 Windows 10 常见故障排查_案例一
    实验案例一:使用Windows安全模式解决系统故障1、实验环境        某公司的计算机全部安装了Windows10操作系统,公司员工由于操作不当,误安装了错误的驱动程序,导致计算机无法正常启动,现需要将错误的驱动程序卸载,2、需求描述通过安全模式进入操作系统卸载掉存在兼容......