EasyDSS视频直播/点播服务平台诞生至今,我们做了不少版本的功能更新和升级,除EasyDSS外,TSINGSEE青犀视频全线平台均有演示平台供参考,用户可以进入演示平台阅览界面,也有测试版本供大家下载测试。若大家有兴趣可以联系我们进行测试。EasyDSS 的视频模块,用户反馈会出现网络请求失败的问题,需要刷新页面则正常显示。
查看后台日志,发现是 /vod/sharelist 接口返回 400 错误,导致的问题。源代码如下:
if !dao.SYSConfig().VODOpenSquare {
c.AbortWithStatus(http.StatusBadRequest)
return
}
用户的现场,视频广场功能已经打开,因此原则上该返回值应该永远不会被调用。因此说明 dao.SysConfig() 函数中返回的系统配置应该是不正确的。
在后台添加打印信息,发现 dao.SysConfig() 在运行过程中确实会出现全部变为初始化值的问题。默认代码如下:
//SYSConfig sytem config
func SYSConfig() *do.TConfig {
if sysConfig != nil {
return sysConfig
}
return SYSConfigLoad()
}
func SYSConfigLoad() *do.TConfig {
sysConfig = &do.TConfig{}
GetDB().Where(consts.SqlWhereID, consts.PlatformID).First(sysConfig)
configSys := &do.TConfigSys{}
GetDB().First(configSys, "local_ip = ?", utils.LocalIP())
//配置外网IP
sysConfig.ExternalIP = configSys.ExternalIP
return sysConfig
}
以上 SysConfig 代码如果不为空则直接返回,会带来以上问题。如果有人在调用 SysConfig() 代码的时候,另外一个部分调用了 SysConfigLoad(),全局的 sysConfig 就会被初始化,因此出现会获取到全部都是初始值的情况。
添加锁的代码,来保证更新配置的时候,不会被其他人读取到。因此修改代码如下:
//SYSConfig sytem config
func SYSConfig() *do.TConfig {
if sysConfig != nil {
sysCfgLock.RLock()
defer sysCfgLock.RUnlock()
return sysConfig
}
return SYSConfigLoad()
}
func SYSConfigLoad() *do.TConfig {
sysCfgLock.Lock()
defer sysCfgLock.Unlock()
sysConfig = &do.TConfig{}
GetDB().Where(consts.SqlWhereID, consts.PlatformID).First(sysConfig)
configSys := &do.TConfigSys{}
GetDB().First(configSys, "local_ip = ?", utils.LocalIP())
//配置外网IP
sysConfig.ExternalIP = configSys.ExternalIP
return sysConfig
}
添加 sysCfgLock 这个 sync.RWMutex{} 类型的读写锁,在更新 sysConfig 的时候,添加上写锁,则其他协程则不会访问成功,来保证读取的数据是最新的。