用 Go 写后台服务,Channel 堆满可以说是高并发场景下的痛点。流量一抖,下游消费跟不上,默认的阻塞写入就会把上游疯狂堆积的协程直接卡死。如果不加干预,几秒钟内节点就可能 OOM。面对这种极端场景,资深的 Go 开发者通常会掏出 select 搭配 default 的组合,靠非阻塞写入硬抗突发流量。接下来就拆解一下这个高频打法的底层逻辑。
业务中经常用有界通道来做异步缓冲,比如日志上报、埋点收集等。平时跑得很顺,可一旦遇到外部 QPS 突增,下游消费速度跟不上,缓冲区分分钟就会被塞满。
这时候再执行 ch <- data,协程就会被死死卡住。外界请求还在源源不断地进来,系统只能疯狂创建新的 Goroutine 去接客,结果全军覆没卡在写通道这一步。很快,内存耗尽,引发 OOM,整个微服务节点直接瘫痪。