进程recv卡住,怎么办?

herofantacy 2023-05-18 11:19:41

进程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性能不高。

以上是我目前全部的分析结果。

...全文
236 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
这个好玩吗 2023-05-21
  • 打赏
  • 举报
回复

"recv卡住": 你的socket fd是设置成非阻塞了吗?如果是非阻塞的,recv的返回值有正确处理吗?(比如特殊判断EAGAIN)
还有看你描述用的是UDP,UDP本身就是不可靠的,假如某个UDP包丢了,那么对方就收不到了,项目里有针对UDP做可靠性的开发吗

herofantacy 2023-05-22
  • 举报
回复
@这个好玩吗 我这不是“某个UDP包丢了”,"recv卡住"是recv长时间卡住
这个好玩吗 2023-05-22
  • 举报
回复
@herofantacy 你没把socket fd设置成非阻塞吧?
这个好玩吗 2023-05-22
  • 举报
回复
@这个好玩吗 fd默认是阻塞的,如果调用recv,但此时缓冲区没有内容就会卡住
赵4老师 2023-05-18
  • 打赏
  • 举报
回复

对方不send了,或网络临时断开或拥塞了,同步recv当然也就卡住了。

69,512

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧