记录一次丢包事故与排查总结

最近出现了一次很严重的组播丢包事故,排查了很长时间才找到原因,特地记录一下

背景

程序本身是单进程、双线程的一个程序,一个线程用来接收网卡上的组播数据,另一个线程将接收到的组播数据再转发出去。数据存取的正确性用一个互斥变量来实现。

现象

发现丢包是因为发现不同机器上下游系统收到的数据量不一致。

这个程序部署在了好几台机器上,组播数据丢包现象经常产生,一般发生在组播数据量最大的时刻,但并非所有程序同时丢包,且丢的包也不一样。

排查

最开始在我们自测的时候并未出现过丢包的问题,因此一开始并未怀疑是程序问题造成的丢包,怀疑可能是环境问题。

首先怀疑是交换机丢包了,但交换机是万兆带宽,且数据量并不是特别大,应该不会出现丢包才对,后来从交换机镜像上抓包后分析,发现确实不是;

后来怀疑可能是程序部署的机器有问题,从机器上抓包分析机器也没有丢包;

那么只可能是程序的问题或者机器处理性能的问题了...

首先了解了一下服务器的配置,至强E系列的4代处理器,24核,32g内存,性能应该是足够的,到这里只能说明是程序处理时产生了丢包现象。

最开始怀疑是程序收发时的处理逻辑有问题,可能引起卡顿导致丢包,但在我们的测试环境下,在差不多的机器配置下,无论怎样修改代码都复现不了丢包的问题...

后来对比了下测试环境的配置文件和生产环境的配置文件,才发现问题:生产上配置了绑核操作和发送线程nowait

结论

由于程序实现的特殊性:单进程双线程,且支持配置绑核(进程层面)和nowait,因此当这两个配置都打开的时候就会出现意想不到的问题:

绑核是进程级别绑定cpu,规定该进程的所有线程都只在该核cpu上运行,nowait是发送线程的一个配置,表明占满cpu运行,nowait打开时,发送线程会占满cpu,同时组播接收线程本身就是非阻塞运行,会占满cpu。因此:

当绑定cpu运行、打开nowait时,接收线程和发送线程就会同时互相抢占该核cpu的资源,该核cpu资源平均分配给两个线程,即组播接收线程只能占用50%左右的cpu资源,当数据量大的时候就可能会出现丢包。

如果不绑定cpu运行且同时打开nowait,那么Linux内核就会自动给两个线程分配到不同的cpu上去,这样的话两个线程就会各自在自己所占用的cpu上跑满,不会丢包

这里分享个查看多线程分别占用资源的方法:
可先用
ps
命令查看进程号,再根据进程号查看不同线程占用的cpu资源情况**

top -H -p <pid>

标题:记录一次丢包事故与排查总结
作者:staymeloo7
联系方式:staycoolsun@gmail.com

    评论
    0 评论
avatar

取消