在可用作在线课堂教育系统的直播点播平台EasyDSS中,如果部署了数量较多的设备作为直播,比如200路以上的直播系统,开启鉴权模块时会导致整个系统的卡顿。
目前EasyDSS视频流作为直播的现有系统架构如下:
1.首先视频流通过 rtmp 协议推送到 C 层;
2.C 层收到推流请求后,发送 /open/live/auth 请求到 Go 层,获取是否可以推流的请求;
3.Go 层收到请求后,根据数据库的结果返回是否可以推流;
4.C 层收到结果后,如果不可以推流,则将流断开。
该种架构的逻辑结构,看起来无问题,但是实际运行中会出现以下情况:
1.如果流不允许推送,C 层会主动断开流。但是对于摄像头来说,还是会继续推流,导致 C 层会发送很多数据到 Go 层判断是否可以推流,存在大量冗余数据。
2.Go 层因为将数据存储在数据库中,首先会从数据库中查询数据,然后数据处理得到结果,返回给 C 层。因此数据的速度,远远小于 1 中 C 请求的速度。因此大量的 1 中的 http 请求在等待响应。
3.因为 Go 层在处理数据,C 层的其他请求在等待,到一定时间会主动断开连接,导致操作系统中出现大量的 CLOSE_WAIT 状态的 socket 存在。
等CLOSE_WAIT出现一段时间后,C层新的http请求会继续发送,Go层继续对新的请求分配资源,直到耗尽自己的资源。出现 too many open files 错误。
最终显现的现象就是网页处于卡死状态,完全无数据。针对此种情况,我们对架构进行优化。
优化一
目前 Go 层的 /open/auth/live 接口,绑定的端口是 10080. 端口,该端口还提供前端网页数据的功能,即:内部逻辑和业务使用了同一个端口。
首先创建 10081 端口,将鉴权 /open/auth/live 接口独占一个端口,防止影响业务。
优化二
针对 CLOSE_WAIT 现象,对 /open/auth/live 接口,添加超时处理,对于已经超时的请求,服务器端强制关闭。
优化三
针对 Go 层数据处理慢的情况,进行如下优化:
1.首先将不需要同步操作的步骤,添加到 Go 协程中处理,优化速度;
2.添加缓存层,以前的数据都是直接从数据库中查询,查询数据耗费时间,添加缓存,加快速度;
3.因为短时间内会存在大量完全相同的请求,因此记录完全相同的请求,如果在固定时间内收到完全相同的请求,则直接使用上一次的结果,然后后台更新请求。在超时时间后,清空对应的结果。
经过以上结构的优化后,Go 层可以很好的处理批量鉴权,前台功能也正常显示。