Open cch123 opened 3 years ago
不从调度器的层面上做些特别的事情感觉很难避免这样的情况吧,只有接受了
@leafduo 不从调度器的层面上做些特别的事情感觉很难避免这样的情况吧,只有接受了
是的,没法解决
这时锁冲突就是会导致整个服务因为锁冲突而直接崩掉(goroutine 暴涨 OOM 之类的,或者延迟大幅上升,不可用)。
这里的goroutine 暴涨 OOM 之类的
是指 goroutine 数量暴涨吗?如果是,那不能怪调度,应该是业务协程池没有控制size的锅。mosn里的那个 pool 就有这个问题,之前跟 taoyuanyuan 聊到过:
https://github.com/mosn/mosn/blob/dc582f2d5086969ec9a4c59ec36a98296d523fd3/pkg/sync/workerpool.go#53
应该也不能怪 rlock 吧,14之后的调度应该是任何一行代码的地方都可能被调度:
package main
import (
"log"
"runtime"
"sync/atomic"
"time"
)
func main() {
n := 2
sum := uint64(0)
runtime.GOMAXPROCS(n)
for i := 0; i < n; i++ {
go func() {
for {
atomic.AddUint64(&sum, 1)
}
}()
}
time.Sleep(time.Second)
for {
log.Println(atomic.LoadUint64(&sum))
time.Sleep(time.Second)
}
}
output:
2021/08/05 15:11:22 66565770
2021/08/05 15:11:23 128544432
2021/08/05 15:11:24 190786970
2021/08/05 15:11:25 253885126
2021/08/05 15:11:26 317599683
...
这时锁冲突就是会导致整个服务因为锁冲突而直接崩掉(goroutine 暴涨 OOM 之类的,或者延迟大幅上升,不可用)。
这里的
goroutine 暴涨 OOM 之类的
是指 goroutine 数量暴涨吗?如果是,那不能怪调度,应该是业务协程池没有控制size的锅。mosn里的那个 pool 就有这个问题,之前跟 taoyuanyuan 聊到过: https://github.com/mosn/mosn/blob/dc582f2d5086969ec9a4c59ec36a98296d523fd3/pkg/sync/workerpool.go#53应该也不能怪 rlock 吧,14之后的调度应该是任何一行代码的地方都可能被调度:
package main import ( "log" "runtime" "sync/atomic" "time" ) func main() { n := 2 sum := uint64(0) runtime.GOMAXPROCS(n) for i := 0; i < n; i++ { go func() { for { atomic.AddUint64(&sum, 1) } }() } time.Sleep(time.Second) for { log.Println(atomic.LoadUint64(&sum)) time.Sleep(time.Second) } }
output:
2021/08/05 15:11:22 66565770 2021/08/05 15:11:23 128544432 2021/08/05 15:11:24 190786970 2021/08/05 15:11:25 253885126 2021/08/05 15:11:26 317599683 ...
这个 rlock 被调度的问题是 1.14 之前就有的问题了 恒定 qps 压测的时候,压了几个小时突然 goroutine 暴涨, 我用 fgprof 曾经看到过是抢锁的 goroutine 突然变多了 这篇只是给出一种可能性,你说的 1.14 都被调度,理论上也确实是有可能的,只不过我当时压还没用 1.14
我觉得即使1.14之前也不应该归咎于rlock,它本身就有runtime_SemacquireMutex的逻辑
如果goroutine暴涨是由于业务层的pool没有限制,那还是要通过业务层来解决
https://xargin.com/schedule-when-holding-lock-causes-latency-spike/