我司开发了一个sip软电话客户端(sip协议常用于网络音视频通讯),基于开源的linphone sdk,使用C# CPF框架开发,.netcore运行时。有windows版本和uos版本。windows版本之前说是要支持视频,CPF里面支持视频只找到一个办法,就是NativeElement控件使用winform的pictureBox来显示,只能用4.x版本的linphone sdk。4.5.26是4.x系列的最后版本,大概2021年的,所以就用它了。集成sdk开发好后,其实没有做充分的压测,只测试了一通长呼叫保持几十小时的情况,没有测大量反复短呼叫的情况。一方面是没有开发相关的压测工具,一方面也过于信任linphone的可靠性,呼了十来通没问题就以为不会出现问题了。现场是win7的系统,上线使用后,时不时发生程序宕机、坐席听不到客户声音的情况。
宕机的问题一开始看日志没有找到准确的原因,后来查看windows系统日志,发现有.net runtime的报错,错误码多是0xc00000005,原因描述是access violation,内存非法访问。配置windows注册表错误报告功能,宕机时将内存dump转储出来dmp文件,配合官方sdk中的pdb文件用windbg分析,都是各式各样的linphone内部异常。
坐席听不到客户声音的问题,发现有出现音频设备接口初始化失败的linphone日志,一开始怀疑是耳机硬件问题。运维说,不太可能,因为不是一直有问题,有时候一通出现问题,下一通又好了。我说,可能耳机短暂接触不良呢。后来发现日志中带有一个错误码88890017,网上一查,是AUDCLNT_E_CPUUSAGE_EXCEEDED,CPU占用率过高。
由于都是linphone内部问题,我们考虑升级linphone sdk版本到5.2.114,或许新版linphone能解决宕机的问题。正好项目上不用sip视频了,所以就升级sdk版本了。另外听不到客户声音的问题,公司有个技术大佬后来开发了一个压测工具,可以对sip发起反复呼叫。压测发现呼叫180多通后必现,跟win7的audiodg.exe进程有关,反复呼叫时这个进程内存一直在缓慢增长,一开始10MB,达到40MB左右时就会报音频设备接口初始化失败的错误。所以做了一个呼叫达到100次自动重启系统音频服务的功能。经过8小时1000多次呼叫压测是正常的,没有再报错。
这是之前的基本情况。
然后客户升级了。升级后,大量出现客户听不到坐席声音的问题。之前是坐席听不到客户声音。一看日志,有一个日志报了个录音设备没有录音能力的错误,更多的日志报的是打开文件失败。我们有的怀疑是麦克风硬件问题,有的怀疑是网络问题。后来禁用麦克风测试,日志出现类似的情况,就主要怀疑是麦克风硬件问题了。打开文件失败怀疑是打开设备文件描述符失败。
然后我们说要测试下麦克风的兼容性,于是我就出差去现场了。到现场拿到耳机进行反复初始化,反复呼叫测试,并没有重现问题。
这时客户报的问题越来越多,一天20多例。我就有点懵逼了。难道是升级导致的?linphone新版或者重启音频服务的功能导致了这个问题?如果是这样问题就是我的责任了。感觉很捉急,压力很大。
这时我们公司的另一个技术大佬出场了。开发总监说技术大佬很厉害,让我找他帮忙看看。之前只找他看了音频设备初始化失败的问题,这时他分析了linphone代码,给出了修改linphone源码的建议。我一脸懵逼,不知道怎么修改。但是我把客户听不到坐席声音的问题也发给他看了。
大佬一看,这就是个打开普通音频文件没有找到文件。过了一会大佬指出sip信令里面有个sendonly,表示媒体协商成了单通。这个原因一找到,事情就解决大半了。不是麦克风硬件有问题,也不是打不开设备文件,而是单通的时候linphone尝试像呼叫保持一样播放一个音乐文件,没有找到那个文件而已。
后续沿这个方向排查,查历史日志,在sip客户端升级前就出现过这个问题了。最后确定问题出在sip网关底层,跟2个月前上线的呼叫保持功能有关系。
从周一到周五排查问题期间是非常紧张的。因为原计划周六进行割接,如果问题不解决,就割接不了,会导致严重的后果。好在最终在周五上午定位并重现了问题。
经过这次排查过程,我充分认识到了自己的技术能力不足,对公司大佬更加佩服了。有的能力不是看书能够学到的,要在实际场景中随机应变,跳出思维定式,需要有充分的实践经验才行。比如sip通信中的sendonly协商,这些书上也不会讲,即使讲了一般也注意不到,遇到一端听不到另一端声音的情况时我也想不到这一点。要不是大佬指点,可能再查两天也找不到原因。
----------------两天后----------------
一波未平,一波又起。周六晚上,割接前,又报了几个sip客户端坐席无声的问题。分析原因是很多呼叫中,会进行IVR验密操作,一次验密会多发两个INVITE事件,导致不到100通呼叫就会出现100多次INVITE,每次INVITE都会触发初始化音频设备的接口调用。接口调用这里可能有内存资源没有释放,导致最终内存不足报错。因为次数计算的差异,也没有能够在报错前自动重启系统音频服务。
甲方还比较讲情理,没有因此停止割接。于是周六晚上上线了1000坐席。周日上午都还正常,到中午13点半就开始出现音频设备初始化失败的问题(Could not initialize the MSWASAPI audio output interface [88890017],有时是8007000e错误码)。下午该问题越来越多,数量惊人。我们紧急修改了几个版本,40通呼叫就重启系统音频服务,以及别的一些逻辑和问题修改。但是这都是治标不治本的办法,还得想办法解决音频内存资源没有释放的问题。
linphone sdk的源码我去年尝试编译过没有成功。这次又重新拿起新版本尝试编译。没想到5.2.114新版本编译步骤自动化了很多,很多库都是自动安装的。结果尝试了一天编译成功了。又请教大佬帮忙看linphone mswasapi模块源码。大佬让我加一些日志运行给他看看。一开始编译后的libmswasapi.dll在win7下不能加载,后来发现编译成debug的dll了,依赖的库是vc redistibutable的debug库。修改成RelWithDebInfo后编译出来的dll能够加载了。大佬看了日志后,找到了内存泄露的地方。
点击查看代码
mswasapi_write.cpp有个bug:
result = mAudioClient->GetService(IID_ISimpleAudioVolume, (void **)&mVolumeControler); //mVolumeControler没有释放。
int MSWASAPIWriter::deactivate()
{
ms_message("MSWASAPIWriter::deactivate()");
RELEASE_CLIENT(mAudioRenderClient);
。。。增加释放mVolumeControler
mIsActivated = false;
return 0;
}
这个问题3年前的4.5.26版本就存在,估计更早的4.x版本也有,一直到今年6月17日的5.2.114版本都没有人发现和解决。win7下呼叫100多次就必现无声的问题,居然3年一直没有人提出来有木有!我们排查了半年多啊有木有!
修改源码后重新编译,再一测试,问题解决了!audiodg.exe内存没有增长了。呼叫1000通都没有增长!
当然事情并不是完全结束了。后续还有一些问题需要解决,比如程序宕机问题,不发心跳问题。
----------------数天后----------------
5.2.114版本linphone通话中拔插耳机崩溃的问题也通过修改mswasapi模块源码解决了。
来电振铃客户放弃和坐席接听时间非常接近导致程序崩溃的问题查了几天,可能也通过修改liblinphone源码解决了,需要进一步测试稳定性。
还剩下一个偶现的不发心跳、不处理sip信令的问题,怀疑也跟前面的音频资源内存泄露有关,目前预期升级修复内存泄露版本后有改善。也在再下一个版本加了一些日志进行排查。
之前的重启音频服务版本也有意料之外问题,有的win7系统上重启没有自动识别到音频设备上线,只能建议升级到修复内存泄露版本了。
看似简单的一个sip客户端软件,遇到的问题多样性和排查解决难度超过了我的想象。linphone windows版本看似成熟实则存在不少问题,可能还是实际应用场景超过了官方测试的覆盖面。
标签:sip,问题,排查,版本,日志,linphone,呼叫,客户端 From: https://www.cnblogs.com/seraph-v3/p/18327993