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/。

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线程的堆栈跟踪

(2)通过交互式终端使用:
go tool pprof http://ip:port/debug/pprof/profile

监控内存溢出 监控器内存满了怎么办_监控内存溢出_02

flat:给定函数上运行耗时
flat%:同上的 CPU 运行耗时总比例
sum%:给定函数累积使用 CPU 总比例
cum:当前函数加上它之上的调用运行总耗时
cum%:同上的 CPU 运行耗时总比例

最后一列为函数名称,在大多数的情况下,我们可以通过这五列得出一个应用程序的运行情况,加以优化。

5、EasyNVR使用pprof工具进行排查后,分析代码发现EasyNVR在项目启动成功,一个开启的通道就是起一个线程一直跑,这个线程一直堵塞着,里面有个定时器,定时获取该通道的快照。现在就相当于有多少路通道就会有多少线程同时跑。而且这个定时获取通道快照涉及到cgo代码,比较耗时和耗费CPU。于是将这一块代码修改为一个定时任务,在这个定时任务里面从所有已开启的通道列表中去获取快照。

6、解决代码

监控内存溢出 监控器内存满了怎么办_定时任务_03

在项目启动时初始化一个资源池

监控内存溢出 监控器内存满了怎么办_定时任务_04

在每个通道开启时将其添加到线程池里面去。修改前开启多少个通道就有多少个线程去获取快照,现在是定时任务里面开启一个线程去获取快照。