用metux lock for循环,在for循环中又 向带缓冲的Channel 写数据时,千万要小心死锁! 背景 用metux lock for循环,在for循环中又 向带缓冲的Channel 写数据时,千万要小心死锁! 最近,我在测试
用metux lock for循环,在for循环中又 向带缓冲的Channel 写数据时,千万要小心死锁!最近,我在测试ws长链接网关,平均一个星期会遇到一次服务假死问题,因为并不是所有routine被阻塞,故runtime的检查无法触发,http health check又是另开的一个端口,k8s检查不到异常,无法重启服务。 经过一番排查论证之后,确定了是 混用带缓冲的Channel和Metux造成的死锁 (具体在文末总结)问题,请看下面详细介绍。 死锁现象 我们使用了gin框架,预先接入了pprof封装组件,这样通过http(非生产)就能很方便的查看go runtime的一些信息。 果不其然,我们打开后发现了大量的 goroutine泄漏: 点开 full goroutiine stack dump,可以看到有很多死锁等待,导致goroutine被阻塞: 其中:
- semacquire阻塞:有9261/2 个 routine
- chan send阻塞:有9处
有一个