前言:
碰到死锁是一个很让人糟心的事情 ! 更让人无语的事, 在测试环境中压力测试了好久都是 ok 的, 一点毛病都没有. 但一到线上的正式环境居然出现死锁了. 主要现象是 队列中的任务不再被消费了, 也没有相关的日志输出. 通过我们业务 stats 接口是可以看到进程内的状态, 队列确实没人消费.
- # xiaorui.cc
- {
- "alert_queue": 0,
- "input_task_queue": 30000, // 这个
- "notify_queue": 30000, // 这个
- "pushing_queue": 0,
- "qps_boss": {
- "15m": 189,
- "1m": 2053,
- "5m": 541,
- "avg": 4112,
- "count": 226029
- },
- "qps_proxy": {
- "15m": 1,
- "1m": 22,
- "5m": 5,
- "avg": 34,
- "count": 1919
- },
- "reporting_queue": 30000,
- "saver_queue": 0,
- "timer_heap_len": 30854,
- ....
- ....
- }
我们知道 golang 是 pmg 模型, 可能出现 goroutine 在不同的线程上浮动. 这样很难通过传统的 pstack 和 strace 分析出问题. 在其他语言里, 你可以使用 strace 追踪关于 mutex 锁的调用, 或者用 pstack 看到调用栈的信息.
- package main
- //xiaorui.cc
- import (
- "time"
- "github.com/rfyiamcool/dump_stack"
- )
- func main() {
- dumpStack.SetupStackTrap()
- // dumpStack.SetupStackTrap("stack.log")
- time.Sleep(100 * time.Second)
- }
- # xiaorui.cc
- awk -F '[' '/goroutine \d*/{print"["$2}' stack.log | sort | uniq -c | sort -k1nr | head -20
- 5030 [select]:
- 1910 [semacquire]:
- 952 [IO wait]:
- 198 [chan send]:
- 11 [sleep]:
- 3 [runnable]:
- 2 [chan receive, 6 minutes]:
- 2 [select, 6 minutes]:
- 1 [chan receive]:
- 1 [IO wait, 1 minutes]:
- 1 [running]:
- 1 [select, 6 minutes, locked to thread]:
- 1 [syscall]:
来源: https://juejin.im/entry/5ad6b03cf265da23a2299fef