TSINGSEE青犀视频接到的许多客户的项目场景都很庞大,一台服务器可能接入几百路甚至上千路摄像头,这种情况就可能就会导致服务器压力大,CPU很容易被占满。
例如,TSINGSEE青犀视频有个项目现场使用的是8核服务器,接入500路摄像头,程序运行几分钟CPU就被占满了。接下来就和大家分享下,我们是如何解决该问题的。
1、首先我们怀疑接入摄像头路数太多了,于是减少接入摄像头路数进行排查,减少到200路、100路、50路,依然会出现CPU占满的情况。于是排除机器性能达不到要求。
2、外部可能排除,于是排查代码。通过golang的pprof(pprof 是用于可视化和分析性能分析数据的工具)工具进行分析排查。
3、在routers的Init方法中添加 pprof.Register(Router),接下来就可以是用pprof工具了。
4、pprof工具有两种使用方式:
(1)第一种通过 Web 界面:http://ip:port/debug/pprof/。
代码语言:javascript复制profiles:
0 block
5 goroutine
3 heap
0 mutex
9 threadcreate
这个页面中有许多子页面:
cpu(CPU Profiling): HOST/debug/pprof/profile,默认进行 30s 的 CPU Profiling,得到一个分析用的 profile 文件
block(Block Profiling):HOST/debug/pprof/block,查看导致阻塞同步的堆栈跟踪
goroutine:$HOST/debug/pprof/goroutine,查看当前所有运行的 goroutines 堆栈跟踪
heap(Memory Profiling): HOST/debug/pprof/heap,查看活动对象的内存分配情况
mutex(Mutex Profiling):HOST/debug/pprof/mutex,查看导致互斥锁的竞争持有者的堆栈跟踪
threadcreate:$HOST/debug/pprof/threadcreate,查看创建新OS线程的堆栈跟踪
goroutine:$HOST/debug/pprof/goroutine,查看当前所有运行的 goroutines 堆栈跟踪 mutex(Mutex Profiling):HOST/debug/pprof/mutex,查看导致互斥锁的竞争持有者 堆栈跟踪
(2)通过交互式终端使用: go tool pprof http://ip:port/debug/pprof/profile
flat:给定函数上运行耗时 flat%:同上的 CPU 运行耗时总比例 sum%:给定函数累积使用 CPU 总比例 cum:当前函数加上它之上的调用运行总耗时 cum%:同上的 CPU 运行耗时总比例
最后一列为函数名称,在大多数的情况下,我们可以通过这五列得出一个应用程序的运行情况,加以优化。
5、EasyNVR使用pprof工具进行排查后,分析代码发现EasyNVR在项目启动成功,一个开启的通道就是起一个线程一直跑,这个线程一直堵塞着,里面有个定时器,定时获取该通道的快照。现在就相当于有多少路通道就会有多少线程同时跑。而且这个定时获取通道快照涉及到cgo代码,比较耗时和耗费CPU。于是将这一块代码修改为一个定时任务,在这个定时任务里面从所有已开启的通道列表中去获取快照。
6、解决代码
在项目启动时初始化一个资源池
在每个通道开启时将其添加到线程池里面去。修改前开启多少个通道就有多少个线程去获取快照,现在是定时任务里面开启一个线程去获取快照。