Диагностика потерь при приёме: NIC, softirq и сетевой стек

Диагностика потерь при приёме: NIC, softirq и сетевой стек

Диагностика потерь при приёме: NIC, softirq и сетевой стек

Периодические тайм-ауты запросов и рост счётчиков отброшенных пакетов на приёме ещё не означают, что сетевая карта неисправна. На выделенном сервере путь приёма проходит через очереди сетевой карты, драйвер, программные прерывания и сетевой стек. Один и тот же симптом может возникать на разных уровнях. При диагностике нужно сопоставлять ошибки приложения с приростом счётчиков за тот же интервал, а не увеличивать все буферы при первом появлении dropped.

Далее используется Debian 12. Потребуются права администратора и инструменты iproute2, ethtool, sysstat, python3. После оплаты выделенного сервера AmdMetal данные для подключения доступны в панели управления; для SSH используется первый адрес IPv4. Сначала мы соберём данные командами, которые ничего не изменяют, не затрагивая адреса и маршруты.

1. Определите интерфейс приёма и интервал сбоя

Сначала с помощью ip -br address найдите интерфейс с адресом, который обслуживает приложение. Затем проследите путь через VLAN, мосты или объединённые интерфейсы до физического интерфейса, по которому действительно проходит трафик. Нельзя просто выбирать первую сетевую карту по алфавиту. В примере ниже интерфейс задаётся интерактивно, а каталог для результатов создаётся автоматически:

read -r -p "Physical interface: " IFACE
ip link show dev "$IFACE" || exit 1
D=$(mktemp -d /var/tmp/rx-audit.XXXXXX)
printf '%s\n' "$IFACE" > "$D/interface"
uname -r > "$D/kernel"
ethtool -i "$IFACE" > "$D/driver"
ip -d link show dev "$IFACE" > "$D/link"
printf '%s\n' "$D"

Зафиксируйте время ошибок приложения, интенсивность запросов, размеры пакетов и наличие массового импорта данных. Накопленные счётчики интерфейса могут охватывать длительное время работы: напрямую связывать их значения с только что возникшим тайм-аутом нельзя. Перезагрузка драйвера, перезагрузка системы или пересоздание интерфейса также могут обнулить счётчики.

Статистика сетевой карты, интерфейса и сетевого стека — не независимые величины, которые можно просто сложить. Некоторые поля могут описывать одно и то же событие. Прежде чем интерпретировать прирост, проверьте определения счётчиков в драйвере.

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

2. Сохраните статистику интерфейса и драйвера за один интервал

Продолжайте в той же оболочке. В примере интервал наблюдения составляет 30 секунд — это параметр сбора данных, а не обещание по обслуживанию. Выберите этап нагрузки, на котором действительно возникает проблема, и соберите контрольные данные за такой же по длительности интервал нормальной работы.

snapshot() {
    label=$1
    date -Is > "$D/$label.time"
    ip -s -s link show dev "$IFACE" > "$D/$label.link"
    ethtool -S "$IFACE" > "$D/$label.nic" 2>&1
    cat /proc/net/softnet_stat > "$D/$label.softnet"
    nstat -az > "$D/$label.protocol"
}
snapshot before
mpstat -P ALL 1 30 > "$D/cpu"
snapshot after
diff -u "$D/before.nic" "$D/after.nic"

Чтение выполняется последовательно, поэтому это не атомарный снимок. При коротких всплесках нагрузки учитывайте временные метки: ожидать совпадения данных из разных файлов с точностью до пакета нельзя. Если ethtool -S сообщает, что операция не поддерживается, сохраните этот результат. «Статистика недоступна» не означает «потерь нет».

Сначала уточните смысл счётчиков

Если растут счётчики ошибок с CRC или frame в названии, ищите подтверждения проблем канального уровня. Для полей с missed, no_buffer или discard необходимо проверить определения в используемом драйвере. Они могут относиться к дескрипторам приёма, буферам устройства или фильтрации; определять причину только по английскому названию нельзя.

Также сохраните вывод ethtool -g "$IFACE" и ethtool -l "$IFACE": первая команда показывает сведения о кольцевых очередях, вторая — о каналах. Отсутствие поддержки этих запросов само по себе не является неисправностью. Максимальные значения обозначают лишь предел возможностей устройства, а не рекомендуемые настройки для рабочей системы.

3. Рассчитайте прирост счётчиков softnet по CPU

Значения в /proc/net/softnet_stat записаны в шестнадцатеричном формате. Первые три столбца — processed, dropped и time_squeeze соответственно. Остальные столбцы могут меняться в зависимости от ядра; здесь мы их не разбираем. Следующий скрипт сравнивает строки и выводит номер строки в собранных данных. Если во время замера происходило горячее подключение или отключение CPU, сбор нужно повторить, а не продолжать механически сопоставлять строки.

python3 - "$D/before.softnet" "$D/after.softnet" <<'PY'
import sys
from pathlib import Path

def load(path):
    return [
        [int(v, 16) for v in line.split()[:3]]
        for line in Path(path).read_text().splitlines()
    ]

before, after = map(load, sys.argv[1:])
if len(before) != len(after):
    raise SystemExit("CPU layout changed; sample again")

print("row processed_delta dropped_delta time_squeeze_delta")
for row, (old, new) in enumerate(zip(before, after)):
    delta = [b - a for a, b in zip(old, new)]
    if any(v < 0 for v in delta):
        raise SystemExit("Counter reset or wrap; sample again")
    print(row, *delta)
PY

Рост dropped здесь указывает на отбрасывание пакетов в программной очереди входящих пакетов. Рост time_squeeze означает, что цикл обработки достиг установленного лимита, но сам по себе не означает потерю пакетов. Статистика softnet агрегируется по CPU, а не по отдельной сетевой карте, поэтому нужно исключить влияние трафика других интерфейсов за тот же период.

Сопоставьте прирост с %soft в выводе mpstat. Даже при низкой общей загрузке сервера одно ядро может испытывать высокую нагрузку на приёме, поэтому среднего значения загрузки недостаточно. При необходимости сохраните /proc/interrupts и проверьте, не сосредоточены ли прерывания очередей сетевой карты на отдельных CPU. Распределение прерываний — лишь диагностический признак, а не требование обязательной равномерности.

4. Выберите уровень настройки по собранным данным

Если счётчики типа missed на сетевой карте растут, а softnet dropped не меняется, в первую очередь проверьте кольцо приёма и очереди драйвера. Если, наоборот, растёт softnet dropped и одновременно перегружено одно ядро, проверьте программную очередь входящих пакетов и распределение трафика. Если обе группы счётчиков стабильны, переходите к приросту протокольных ошибок в nstat и журналам приложения, а не продолжайте менять настройки сетевой карты вслепую.

Перед изменениями сохраните текущую конфигурацию:

ethtool -g "$IFACE" > "$D/rings" 2>&1
ethtool -l "$IFACE" > "$D/channels" 2>&1
sysctl net.core.netdev_max_backlog \
       net.core.netdev_budget \
       net.core.netdev_budget_usecs > "$D/budgets"

Изменять размер кольца стоит только при поддержке со стороны драйвера и наличии соответствующих свидетельств. Установка максимального значения — не универсальное решение. Увеличение очереди может сократить число отброшенных пакетов ценой большей задержки ожидания, а повышение лимита обработки — отнять процессорное время у приложения. При настройке распределения по нескольким очередям необходимо учитывать IRQ, RSS и число потоков трафика. Один поток от этого не начнёт автоматически распределяться по всем ядрам.

При удалённой работе не следует сразу пробовать перенастройку каналов, перезагрузку драйвера или сброс линка. Эти действия могут нарушить SSH-соединение. Сначала подготовьте план контролируемых действий, сохраните исходные значения и предусмотрите способ восстановления. За один цикл меняйте только один параметр; при отклонениях сначала верните исходное значение.

5. Подтвердите результат повторным тестом приложения

При повторном тесте сохраняйте сопоставимые типы запросов, длительность и характер параллельной нагрузки, одновременно фиксируя фактический трафик. Сравнение только абсолютного числа отброшенных пакетов за два интервала может выдать снижение нагрузки за успешную оптимизацию. Даже при одинаковой пропускной способности большее число мелких пакетов может создавать другую нагрузку на обработку приёма.

Для приёмки нужны как минимум три группы результатов:

Если счётчики нижних уровней стабильны, но ошибки приложения продолжаются, ограничьте вывод формулировкой: «За этот интервал не обнаружено свидетельств соответствующих потерь на приёме». Продолжайте проверять сетевой стек и обработку в приложении, не объявляя сеть полностью исправной. Сохраните сведения об интерфейсе, драйвере и ядре, файлы замеров и исходные значения изменённых настроек — это позволит повторно проверить причинную связь, когда тот же симптом появится снова.

Часто задаваемые вопросы

Рост dropped в ip -s link доказывает неисправность сетевой карты?

Нет. Агрегированный счётчик нужно сопоставить со статистикой драйвера, ошибками линии и симптомами за тот же интервал. Складывать все поля со словом drop без проверки их определения нельзя.

Рост time_squeeze означает потерю пакетов?

Сам по себе — нет. Он показывает достижение предела бюджета обработки приёма. Нужны также прирост dropped, нагрузка softirq по ядрам и ошибки приложения.

Выделенный сервер AMD EPYC 7543P

от $458.7/мес.

Настроить сервер AmdMetal Цены на серверы AmdMetal

Проверка конфигурации сервера по пунктам

Полностью выделенный AMD EPYC 7543P; модель и дополнительные опции рассчитываются на странице конфигурации.