Назад | Перейти на главную страницу

Высокая средняя нагрузка, но низкая загрузка ЦП и дискового ввода-вывода

Я столкнулся со странной проблемой на одном из моих серверов. Это KVM VPS с одним выделенным ядром ЦП.

Иногда нагрузка резко возрастает до 2,0:

Однако загрузка ЦП на самом деле не увеличивается в течение этого периода, что также исключает причину iowait:

Это кажется периодическим, когда это происходит (например, на этом графике это происходит примерно каждые 20-25 минут). Я подозревал, что это cronjob, но у меня нет cronjobs, которые запускаются каждые 20 минут. Я также попытался отключить свои cronjobs, но скачок нагрузки все еще происходит.

Мне удалось действительно увидеть, как это происходит, когда SSH подключился к серверу ... У него была нагрузка 1,88, но процессор был на 94% в режиме ожидания и было 0% iowait (это то, что, как я ожидал, могло быть)

Когда это происходит, операций ввода-вывода на диске не наблюдается.

Я в тупике. Любые идеи?

Итак, я решил это ... Оказывается, это было вызвано программным обеспечением, которое я использовал для мониторинга сервера (Netdata).

Linux обновляет среднюю нагрузку каждые 5 секунд. Фактически, он обновляется каждые 5 секунд плюс одна отметка.

sched / loadavg.h:

#define LOAD_FREQ   (5*HZ+1) /* 5 sec intervals */

sched / loadavg.c

 * The global load average is an exponentially decaying average of nr_running +
 * nr_uninterruptible.
 *
 * Once every LOAD_FREQ:
 *
 *   nr_active = 0;
 *   for_each_possible_cpu(cpu)
 *  nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible;
 *
 *   avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n)

HZ - частота таймера ядра, которая определяется при компиляции ядра. В моей системе это 250:

% grep "CONFIG_HZ=" /boot/config-$(uname -r)
CONFIG_HZ=250

Это означает, что каждые 5,004 секунды (5 + 1/250) Linux вычисляет среднюю нагрузку. Он проверяет, сколько процессов активно запущено, а также сколько процессов находится в состоянии непрерывного ожидания (например, ожидания ввода-вывода диска), и использует это для вычисления средней нагрузки, экспоненциально сглаживая ее с течением времени.

Допустим, у вас есть процесс, который каждую секунду запускает кучу подпроцессов. Например, Netdata собирает данные из некоторых приложений. Обычно процесс выполняется очень быстро и не перекрывается с проверкой средней нагрузки, поэтому все в порядке. Однако каждые 1251 секунду (5,004 * 250) интервал обновления средней нагрузки будет точным кратным одной секунде (то есть 1251 является наименьшим общим кратным 5,004 и 1). 1251 секунда - это 20,85 минуты, это именно тот интервал, который я наблюдал при увеличении средней нагрузки. Мое обоснованное предположение состоит в том, что каждые 20,85 минут Linux проверяет среднюю нагрузку в то время, когда несколько процессов запускаются и находятся в очереди на выполнение.

Я подтвердил это, отключив netdata и вручную посмотрев среднюю нагрузку:

while true; do uptime; sleep 5; done

Через 1,5 часа не увидел любой подобные шипы. Шипы только возникают, когда Netdata запущена.

Итак ... в конце концов ... Приложение, которое я использовал для отслеживания нагрузки, было причиной ее возникновения. Иронично. Он мог спасти других от смерти, но не себя.

Оказывается, другие люди сталкивались с подобными проблемами в прошлом, хотя и с разными интервалами. Следующие сообщения были чрезвычайно полезны:

Сообщил об этом разработчикам Netdata здесь: https://github.com/netdata/netdata/issues/5234. В конце концов, я не уверен, что назвал бы это ошибкой, но, возможно, netdata может реализовать некоторый джиттер, чтобы он не выполнял проверки каждую секунду точно.