我们运行一个Linux应用程序,它分派了大量(超过1000个)子进程。这些子进程通过UNIX数据报套接字与主进程进行通信(所有子进程之间共享一个进程)。 UNIX数据报套接字除了用于记录的其他通信之外也被使用。整个系统运行良好,直到应用程序必须对一个巨大的外部错误做出反应 - 比如说应用程序数据库崩溃。我们观察到,在这种情况下,子进程开始产生大量错误日志事件,这可能是正确的,因为每个子进程都会受到该崩溃的影响。几分钟后,80-100%CPU 系统(非用户!)消耗的负载增加到8000以上。只有当应用程序被杀或更常见时才能恢复状态,由于响应缓慢并且必须重新启动,该状态变为不可用。在Linux UNIX套接字上实时锁定,该怎么办?
对核心转储的调查显示子进程在UNIX套接字上的系统调用send()
中被阻塞,与主进程对话。 UNIX套接字被配置为非阻塞,并且该应用实现了EAGAIN
的正确处理。更深入的分析表明内核中存在活锁状态。显然,进程正在竞争访问与UNIX套接字相关的一些资源。
问题:你曾经遇到过这种或类似的行为吗?我们错过任何关于UNIX套接字并行性的事情吗?
版本:
- CentOS Linux版本7.3.1611(核心)。
- 内核Linux 3.10.0-514.16.1.el7.x86_64 x86_64。
我不会说他们在send()中被“封锁”,只是他们将大部分的处理时间花费在那里。套接字缓冲区是否可能已满?无论如何,考虑内核中的错误将是我最后的选择。 –
套接字缓冲区是最确定的,但它通常通过EAGAIN机制处理b/c UNIX套接字是非阻塞的。我同意内核bug部分。 –
如果在不成功的发送之间没有延迟(例如睡眠),这是您将得到的结果。 –