2017-06-15 49 views
0

我们运行一个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。

+0

我不会说他们在send()中被“封锁”,只是他们将大部分的处理时间花费在那里。套接字缓冲区是否可能已满?无论如何,考虑内核中的错误将是我最后的选择。 –

+0

套接字缓冲区是最确定的,但它通常通过EAGAIN机制处理b/c UNIX套接字是非阻塞的。我同意内核bug部分。 –

+1

如果在不成功的发送之间没有延迟(例如睡眠),这是您将得到的结果。 –

回答

0

在这方面,内核方面显然有改进的余地,而且很可能是一个相当低的挂果。我不会推测。使用火焰图很容易看出问题的可能性。

但是,在这种情况下,排序的考虑因素是红鲱鱼。为了说明起见,我们假设内核以0开销推送所有这些错误消息。您已经生成了千兆字节的重复性错误消息,但没有添加任何值。

相反,当有重大事件只要登录其一次,然后重新登录,它被清除(如注意与数据库的连接去世,注意当它得到了回升,但不要每次登录查询它已经死了)。或者,您可以定期或使用ratelimit进行记录。无论哪种方式,只是垃圾邮件是不对的。

孩子的数量(1000多个?)看起来非常过分,并且对这个项目的设计的有效性提出了一个问号。你能详细说明那里发生了什么?

+0

让我们从头开始:我完全同意,具有大量子进程的设计至少是奢侈的。决策的最初目的来自安全性:每个孩子处理通过唯一密钥集加密的对等连接,并且意图是在系统/过程级别保持分离。性能方面也相当令人印象深刻,它可轻松处理+ 10k并发连接,每秒处理250个事务,占用CPU的1-5%,系统负载小于0.1。但我不是为了辩护这一点,下一代可能会转而采用“每CPU核心处理器”模式。 –

+0

重大事件和'管理'日志记录:是的,这是一个很好的观察。但是,这并没有解决根本问题。还有其他方式可以触发广泛的日志记录,从而调用应用程序的停滞。 –

+0

Re“千兆字节的重复性错误消息不增加任何值” - 这个应用程序生成了一个巨大的审计日志,它被输入到一个功能强大的日志分析器中。从这个角度来看,这些错误在海洋中下降。类似的情况(当不拖延应用程序时)会在监控图表中产生一个“漂亮”峰值,以便操作员快速响应。但是,我不再为此辩护 - 这是一个明显的改进空间,可能是单一但更严重的日志消息。 –