Ticker 未释放导致的 CPU 占用过高

问题描述

2018-12-15, 辅导服务一台服务器的 TCP 连接数忽上忽下(如下图), 上下浮动在400~500的数量. 而此时 CPU 一直在满负载, 内存占用很高(如下图). 导致用户无法正常上课.

问题缘由

1. TCP 连接中, 存在全球各地的 IP, 并且数量占比很高, 存在恶意攻击的可能.

2. 辅导服务会为每个 TCP 连接都会创建一个 ticker, 并且没有释放. time.NewTicker() → time.startTimer() → runtime.addtimer() → runtime.addtimerLocked() → runtime.timerproc() → runtime.siftdownTimer().

    每来一个 TCP 连接, ticker 会新增, timerproc 是唤醒处理定时器的一个函数. golang使用的最小堆维护的一个timer队列, go比较费时,每次操作最坏情况下都是logn(n为时间队列长度).

    新建了很多 ticker, 资源未释放, 导致内存占用过高.

经验教训

Never call time.NewTicker(…) within a fast iterating for loop.

Stop the ticker to release associated resources.

参考资料:

                 https://zhuanlan.zhihu.com/p/30268582

                 https://guidao.github.io/go_timer.html

                 https://forum.golangbridge.org/t/runtime-siftdowntimer-consuming-60-of-the-cpu/3773

posted @ 2019-08-22 20:26  Zereker  阅读(1587)  评论(0编辑  收藏  举报