Я столкнулся со странной проблемой на одном из моих серверов. Это KVM VPS с одним выделенным ядром ЦП.
Иногда нагрузка резко возрастает до 2,0:
Однако загрузка ЦП на самом деле не увеличивается в течение этого периода, что также исключает причину iowait:
Это кажется периодическим, когда это происходит (например, на этом графике это происходит примерно каждые 20-25 минут). Я подозревал, что это cronjob, но у меня нет cronjobs, которые запускаются каждые 20 минут. Я также попытался отключить свои cronjobs, но скачок нагрузки все еще происходит.
Мне удалось действительно увидеть, как это происходит, когда SSH подключился к серверу ... У него была нагрузка 1,88, но процессор был на 94% в режиме ожидания и было 0% iowait (это то, что, как я ожидал, могло быть)
Когда это происходит, операций ввода-вывода на диске не наблюдается.
Я в тупике. Любые идеи?
Итак, я решил это ... Оказывается, это было вызвано программным обеспечением, которое я использовал для мониторинга сервера (Netdata).
Linux обновляет среднюю нагрузку каждые 5 секунд. Фактически, он обновляется каждые 5 секунд плюс одна отметка.
#define LOAD_FREQ (5*HZ+1) /* 5 sec intervals */
* 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 может реализовать некоторый джиттер, чтобы он не выполнял проверки каждую секунду точно.