68,372
社区成员




进程A出现recv()一段时间内卡住,是什么原因,怎么解决问题,防止再次出现?各位能分析出什么?有什么建议?
进程A是单线程,从其它的IP端口,通过select(),来通过recv()接收消息。
进程A(localhost.localdomain.端口A)从其它主机的进程B(IP和端口),每30毫秒接收2条消息,之后每30毫秒向其它主机的进程C通过sendto()发送消息,进程A的实时性要求很高。
可以明确的现象是:
进程C长时间收不到进程A的消息,触发告警。
通过打印的日志分析如下:
①进程A打印日志1,日志1在日志1中从11:38:25.534668到11:38:35.470901这10秒内没有收到从进程B来的消息的日志打印,也没有任何打印。
②在日志1中从11:38:35.470901到11:38:35.698822这之间内,至少每1毫秒从进程B收到一条消息
③本地进程D(检测进程D)通过定期用命令"netstat -nap | grep 端口A" 查询,检测进程D打印的日志2如下
在期间半个小时之内netstat 共查询了900次,以下结果打印了840次
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
以下结果打印了48次,概率性每5次-25次出现一次
udp 832 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
以下结果打印了9次,概率性每2次-300次出现一次
udp 1664 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
出问题的时间点(11:38:25到之间)打印如下
udp 339456 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
日志2的片段如下
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 1664 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 832 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
udp 0 0 0.0.0.0:端口A 0.0.0.0:* 19422/进程A名称
通过分析日志2,像是接收队列阻塞了339456个数据,像是CPU卡住了,据同事说CPU性能不高。
以上是我目前全部的分析结果。
"recv卡住": 你的socket fd是设置成非阻塞了吗?如果是非阻塞的,recv的返回值有正确处理吗?(比如特殊判断EAGAIN)
还有看你描述用的是UDP,UDP本身就是不可靠的,假如某个UDP包丢了,那么对方就收不到了,项目里有针对UDP做可靠性的开发吗
对方不send了,或网络临时断开或拥塞了,同步recv当然也就卡住了。