...

Server IRQ Affinity и оптимизация многоядерной сети для максимальной производительности

Я оптимизирую сетевые пути сервера следующим образом Сродство IRQ и сопоставляйте очереди RX/TX с ядрами, чтобы контролировать задержку, пропускную способность и джиттер p99. Те, кто использует многоядерные процессоры, последовательно организуют прерывания, SoftIRQ, NAPI и NUMA таким образом, чтобы потоки оставались без ядра, переключение контекста сокращалось, а приложение реагировало заметно быстрее.

Центральные пункты

  • Распределение IRQ определяет, какие ядра передают аппаратные прерывания, и предотвращает появление "горячих точек".
  • Близость NUMA сокращает удаленный доступ и снижает пиковые задержки.
  • SoftIRQs и NAPI управлять пакетной обработкой и снижать нагрузку на ядра.
  • RPS/RFS держит потоки вблизи потребляющих потоков.
  • Измерения и штифтование делает производительность более детерминированной.

Почему IRQ Affinity имеет значение для работы сервера

Высокая скорость передачи пакетов быстро создает нагрузку на отдельные ядра, если все прерывания приходятся на несколько процессоров, поэтому я распределяю нагрузку выборочно, чтобы Горячие точки чтобы избежать этого. Я назначаю очереди RX/TX на соответствующие ядра, чтобы пути передачи данных были короткими, а кэши - теплыми. Это уменьшает задержки p95/p99, поскольку я избегаю ненужных миграций и сохраняю этапы обработки на одних и тех же ядрах. Я учитываю физическую близость сетевых карт, каналов памяти и сокетов процессора, чтобы путь от пакета до рабочего приложения оставался неизменно быстрым. Такая привязка к ядрам обеспечивает ощутимую стабильность во время пиков трафика без необходимости немедленного обновления оборудования.

Балансировка IRQ в сравнении с фиксированным сродством

Стандартная услуга irqbalance распределяет прерывания автоматически, но он не знает логику моего приложения, цели NUMA и бюджеты задержек. Я привязываю критические сетевые IRQ к выбранным ядрам, в то время как шумные или менее важные прерывания переходят к другим ядрам. Эта привязка гармонично сочетается с привязкой прикладных процессов, так что конвейер на поток остается неизменным. При интенсивном трафике я избегаю перераспределения, которое создает дополнительные накладные расходы и ослабляет эффект кэша. Если вы хотите углубиться, то можете найти практическую справочную информацию в этом руководстве: Балансировка IRQ в центре обработки данных.

Сродство процессора, NUMA и короткий путь данных

Я предпочитаю подключать рабочие приложения и сетевые IRQ к одному и тому же NUMA-узлов, чтобы доступ к памяти оставался локальным. Если сетевая карта висит на узле 0, я также устанавливаю там соответствующие очереди RX и привязываю соответствующие процессы к этим ядрам. Таким образом, я избегаю дорогостоящих удаленных обращений к памяти, которые сильно влияют на задержку при высокой скорости передачи пакетов. Я также включаю пары гиперпотоков, чтобы сестринские потоки не мешали друг другу. Этот треугольник из привязки процессов, IRQ и топологии NUMA делает сетевые маршруты более предсказуемыми и повышает пропускную способность.

Понимание SoftIRQs, NAPI и дизайна очередей

После аппаратного прерывания ядро берет на себя обработку в SoftIRQs, часто на том же ядре, которое получило IRQ. Когда нагрузка высока, я сознательно распределяю нагрузку SoftIRQ, чтобы уменьшить узкие места без излишней фрагментации пути передачи данных. Многоочередные сетевые карты помогают, потому что я могу назначить четко определенные ядра для каждой очереди и таким образом добиться истинного распараллеливания. Я использую NAPI для пакетной обработки пакетов, чтобы не возникало штормов прерываний и процессорное время использовалось эффективно. В этой статье приведены справочные сведения об этом пути: SoftIRQ и пропускная способность сети.

RPS/RFS и локальность потока

Я использую RPS для более широкого распространения пакетов и устанавливаю RFS чтобы потоки попадали в потоки-потребители. Это обеспечивает эффективный доступ к кэшу, а приложение выигрывает от стабильного времени отклика. Я согласовываю стратегию хэширования сетевой карты, количество очередей и наборы процессоров RPS так, чтобы ни одна очередь ядра не переполнялась. Сродство потоков особенно эффективно для многих коротких запросов, таких как те, что генерируются API и микросервисами. Таким образом, я строю конвейер, в котором каждый поток как можно чаще обращается к одному и тому же ядру, и избегаю ненужных миграций.

RSS, таблица перенаправления и XPS: целенаправленный контроль хэширования

Чтобы обеспечить чистый запуск дистрибутива на сетевой карте, я настраиваю RSS (Receive Side Scaling) и таблицу перенаправления, чтобы очереди RX были назначены именно тем ядрам, на которых впоследствии будут работать потоки приложения. Я слежу за тем, чтобы количество очередей соответствовало количеству используемых ядер и чтобы хэш-ключи оставались стабильными, чтобы потоки не перемещались неожиданно. Если алгоритм хеширования меняется или таблица перенаправления динамически перезаписывается, это нарушает локальность потоков и способствует промахам в кэше.

На пути TX я дополнительно активирую XPS (Transmit Packet Steering), чтобы исходящие пакеты отправлялись тем ядром, которое обрабатывает приложение. Это также позволяет держать кэши TX близко к рабочему ядру, и путь от очереди сокетов до очереди сетевых карт остается коротким. Я поддерживаю согласованное сопоставление RX и TX, документирую их для каждого интерфейса и определяю в сценариях запуска, чтобы перезагрузка не нарушала архитектуру.

Коалесцирование прерываний: соизмерение задержки и пропускной способности

С Коалесцирующий Я суммирую прерывания, чтобы уменьшить накладные расходы, но при этом обращаю внимание на ограничения по задержкам моего приложения. Для потоковой передачи и VoIP я стараюсь держать интервалы короткими, в то время как массовые передачи хорошо переносят более длинные пакеты. Я тестирую шаг за шагом, измеряю p95/p99 и проверяю падения, ретрансляции и загрузку процессора на ядро. Только после этого я записываю настройки и документирую их для каждого хоста и сетевой карты. Эта практическая статья дает более глубокое представление о компромиссе: Объяснение коалесценции прерываний.

Правильное дозирование разгрузки и агрегации

Я установил GRO/LRO чтобы снизить нагрузку на процессор, но проверьте, выигрывают ли мои рабочие нагрузки от больших пакетов. API, чувствительные к задержкам, часто лучше реагируют, когда GRO умерен, а LRO выключен, поскольку большие суперпакеты могут усилить эффект блокировки в голове линии. При массовых передачах, репликации или резервном копировании я использую GRO/GSO/TSO более активно, пока принимающая сторона остается стабильной и загрузка процессора снижается.

Выгрузка контрольных сумм и TSO/GSO значительно снизить нагрузку на центральный процессор, но я убеждаюсь, что промежуточные устройства, туннели или несовместимость разгрузки (например, с определенными инкапсуляциями) работают должным образом. Если возникают аномалии, я постепенно уменьшаю отдельные разгрузки и измеряю влияние на пропускную способность, ретрансляции и процессорное время. Цель - получить набор, который остается стабильным по всем параметрам и предсказуемым в пиковые моменты.

Изоляция процессора, планировщик и энергетические состояния

При жестких ограничениях на задержку я выделяю ядра для сетевых путей и рабочих приложений. С помощью Изоляция процессора и стратегии бережливого домоводства, я предотвращаю попадание системных задач, Kthreads или таймерных прерываний на „горячие“ ядра. Я также исправляю Управление процессором на „производительность“ и ограничить глубокое C-состояния, если они вызывают задержки при пробуждении. Я слежу за температурой ядра, поскольку тепловое гниение может испортить все последние штрихи.

Выбор Расписание занятий влияет на предсказуемость. Я отдаю приоритет потокам, связанным с сетью, но не запускаю их агрессивно и эксклюзивно, чтобы они не конкурировали с ksoftirqd за процессорное время. Я регулярно проверяю, запускается ли ksoftirqd на отдельных ядрах - это явный признак того, что нагрузка на SoftIRQ слишком высока или неправильно распределена.

Опрос в режиме ожидания и пути с низкой задержкой

Когда счет идет на микросекунды, я устанавливаю Занятый опрос целенаправленно. Приложения могут определить окна опроса для выбранных сокетов, чтобы они получали пакеты непосредственно из бюджетов NAPI, не дожидаясь прерываний. Я выбираю короткие интервалы опроса, чтобы не сжигать процессорное время, и ограничиваю эту технику горячими путями с постоянным трафиком. Параллельно я адаптирую бюджеты netdev умеренно, чтобы партии были достаточно большими и не приводили к голоданию остальной системы.

Дисциплина сетевых очередей и темп работы

Я установил qdisc на интерфейс в соответствии с рабочей нагрузкой. Я использую современные дисциплины, такие как fq/fq_codel, для регулирования темпа и длины очередей, чтобы сгладить всплески и избежать буферного вздутия. В многоочередных системах я комбинирую это с mqprio, Таким образом, классы трафика неизменно назначаются правильным очередям HW. Вместе с BQL (Byte Queue Limits) на драйвере уменьшает задержку при полной нагрузке, поскольку очередь не растет бесконтрольно.

Важно взаимодействовать с XPS на пути TX: Я назначаю очереди отправки на ядра, на которых также располагаются соответствующие потоки RX. Таким образом, оба направления потока остаются близко к процессору, и я добиваюсь более стабильного времени отклика при работе с двунаправленными протоколами (например, HTTP/2, gRPC).

Практический рабочий процесс в Linux

Я начинаю с записи нагрузки, проверяю распределение процессора в top/htop, смотрю /proc/interrupts и /proc/softirqs и читаю статистику ethtool, чтобы выявить узкие места и подготовиться к следующей работе. Рабочий процесс-шаг. Затем я определяю IRQ ID соответствующих очередей NIC и устанавливаю подходящие маски CPU, которые равномерно занимают ядра и учитывают NUMA. Затем я прикрепляю рабочие приложения с помощью наборов задач или systemd-CPUAffinity к тем же ядрам, которые также обслуживают соответствующие очереди. Я активирую RPS/RFS только там, где это усиливает локальность потока, и сохраняю последовательность конфигурации для каждого интерфейса. Наконец, я снова измеряю пропускную способность, задержку и джиттер, прежде чем равномерно распространить изменения на несколько хостов.

Измерения, избегайте p95/p99 и регрессий

Я не полагаюсь на интуицию, а измеряю задержки, количество ошибок и загрузку ядра до и после каждого раунда настройки, чтобы p99 остается стабильным. Я также отслеживаю изменения контекста, скорость миграции и нагрузку на каждый тип SoftIRQ, чтобы выявить скрытые побочные эффекты на ранних стадиях. Я поддерживаю воспроизводимость тестов, использую одни и те же наборы данных и фиксированные версии, чтобы результаты оставались сопоставимыми. Я выявляю регрессии с помощью перекрестных проверок в условиях пиковой нагрузки и простоя, а также в ходе длительных испытаний на выносливость. Только когда метрики, журналы и трассировки приложений совпадают, я объявляю конфигурацию новым базовым состоянием.

Виртуализация, контейнеры и SR-IOV

В виртуальных средах я слежу за тем, чтобы виртуальные процессоры, память и сетевые карты виртуальной машины расположены на том же узле NUMA, на котором находится соответствующая физическая сетевая карта. Там, где это возможно, я использую SR-IOV, чтобы путь данных был коротким и IRQ можно было привязать непосредственно к гостевым ядрам. Я подключаю vCPU критических ВМ к выделенным ядрам хоста и слежу за тем, чтобы IRQ хоста и гостевые IRQ не пересекались. В контейнерных установках я устанавливаю cpusets и „гарантированные“ классы QoS, чтобы рабочие контейнеры и их сетевые IRQ получали процессорное время предсказуемым образом.

Я проверяю, должен ли irqbalance иметь ведущую роль в госте или на хосте - иначе двойной „автомат“ приводит к размытию. В virtio я устанавливаю несколько очередей и сопоставляю их с vCPU, чтобы обеспечить параллельную работу. Если vhost-net использует отдельные ядра хоста, я перераспределяю бэкенды и держу потоки vhost в NUMA-близости от физической сетевой карты.

Устранение неполадок: быстрое распознавание деталей

  • Ядра насыщены, ksoftirqd активны: Расположите очереди RX ближе друг к другу, проверьте количество очередей, настройте RPS/RFS или немного увеличьте коалесцирование.
  • Прыгучесть p99: Проверьте дрейф NUMA, проверьте C-States/Governor, пошагово настройте разгрузку и размеры GRO.
  • Много ретрансляций/пропаданий: Проверьте размеры колец RX/TX, qdisc и BQL, проверьте таблицу перенаправления и XPS на согласованность.
  • Неравномерное распределение потоков: Сбалансируйте хэш RSS и таблицу перенаправлений, учитывайте распиновку горячих потоков, поддерживайте стабильность семян хэша.
  • Проблема только с виртуальной машиной: Разместите бэкенды vhost/virtio рядом с NUMA, оцените SR-IOV, разделите IRQ между хостом и гостем.

Включите приложения и базы данных

От чистого сетевого пути мало толку, если серверы приложений или базы данных не работают параллельно, поэтому я настроил Рабочий-число, пулы потоков и лимиты соединений в соответствии с доступными ядрами. Я прикрепляю рабочие NGINX или HAProxy к соответствующим ядрам, чтобы они соответствовали очередям RX. Я масштабирую PHP-FPM, Node.js, Java или Go так, чтобы они предпочитали локальный домен NUMA и использовали несколько экземпляров, если это необходимо. Я интегрирую кэши, такие как Redis или Memcached, рядом с процессором и обращаю внимание на их собственные сетевые и потоковые параметры. Только взаимодействие сродства к IRQ, привязки процессов и масштабирования приложений дает заметный прирост задержки и пропускной способности.

Сценарии размещения с высокой выгодой

В основном я занимаюсь глубокой настройкой, когда API генерирует много коротких запросов или когда Реальное время-Коммуникации, такие как VoIP и чаты, требуют низких значений джиттера. Установки электронной коммерции с пиковыми нагрузками выигрывают, поскольку потоки оформления заказа чувствительны к задержкам. Многопользовательские хосты с высокой плотностью размещения выигрывают, поскольку выделенные ядра на очередь снижают эффект соседства. Потоковые сервисы также могут достичь большей пропускной способности в расчете на евро без немедленной покупки нового оборудования. Затраты остаются просчитываемыми до тех пор, пока я измеряю изменения и аккуратно их внедряю.

Краткая справочная таблица: ядра, очереди, инструменты

Я использую следующее Таблица в качестве напоминания при настройке новых узлов или калибровке существующих. В нем показаны типичные цели, соответствующие меры, распространенные инструменты Linux и предполагаемое влияние на задержку и пропускную способность. Я не использую его догматически, но как отправную точку для серии измерений с реальным трафиком. Если архитектура сетевой карты или топология NUMA меняются, я адаптирую выбор ядра. По-прежнему важно сохранять документацию для каждого узла и отслеживать изменения.

Цель Измерение Инструмент/местоположение в Linux Ожидаемый эффект
Распределение нагрузки на IRQ Привязать сигналы к сердечникам /proc/irq/*/smp_affinity Меньше точек доступа, больше постоянных задержек
Увеличение локальности потока Установка наборов процессоров RPS/RFS /sys/class/net/*/queues/*/rps_cpus Меньше миграций, лучшие кэши
Управление пакетной обработкой Тонкая настройка NAPI/коалесцирования ethtool -C / драйвер по умолчанию Низкие накладные расходы, контролируемый джиттер
Сопряжение приложения и IRQ Рабочий на булавке набор задач, systemd CPUAffinity Короче путь, ниже p99
Избегайте NUMA Совместное размещение устройств и ядер numactl, lscpu, lspci -vv Меньше удаленного доступа, больше пропускной способности

Лучшие практики, которые работают в долгосрочной перспективе

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

Краткое резюме

Я добиваюсь максимальной производительности сети, используя прерывания, Кии и рабочих, что позволяет поддерживать стабильность пути передачи данных на поток. IRQ Affinity разумно распределяет аппаратную нагрузку, а SoftIRQs, NAPI и RPS/RFS делают обработку эффективной. Близость NUMA защищает от нежелательных обходов памяти и снижает джиттер. Пошаговая настройка с воспроизводимыми измерениями предотвращает неправильную конфигурацию и демонстрирует реальный прогресс. Если вы рассмотрите все эти компоненты вместе, то сможете уверенно использовать возможности современных многоядерных серверов для критически важных сервисов.

Текущие статьи

Серверная стойка с сетевым оборудованием для оптимизации сродства IRQ и производительности многоядерной сети
Серверы и виртуальные машины

Server IRQ Affinity и оптимизация многоядерной сети для максимальной производительности

Узнайте, как с помощью функции Server IRQ Affinity и оптимизации многоядерных сетей ускорить обработку пакетов и максимально использовать многоядерные сети в хостинге.

Серверная стойка с SSD-накопителем в современном центре обработки данных
Базы данных

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

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

Серверная стойка в центре обработки данных с визуализированными потоками данных TLS для быстрых HTTPS-соединений
Безопасность

Возобновление рукопожатия TLS и кэширование сеансов для максимальной производительности HTTPS

Исчерпывающее руководство по возобновлению рукопожатия TLS и кэшированию сессий для повышения производительности HTTPS с упором на оптимизацию рукопожатия ssl.