Потери на сетевых картах и как с ними бороться

Skip to end of metadata
Go to start of metadata
Вы просматриваете старую версию данной страницы. Смотрите текущую версию. Сравнить с текущим  |   просмотр истории страницы

В производительность модуля фильтрация не упирается, как правило единственной проблемой при запуске бывает не совсем корректное работающее по умолчанию оборудование (процессор, сетевые карты). Мы много сталкивались с этим, поэтому готовы помочь с настройкой этого оборудования для обеспечения отличной производительности.

Есть четыре вещи которые в основном влияют на потерю пакетов при приёме (допустим, нас не волнует как долго он будет проходить через нашу систему, то есть latency мы можем жертвовать), а наша задача - поймать все пакеты, не упустив ни одного и обработать.

Итак, вещи:

  • размер буфера сетевой карты
  • правильное распределение прерываний входящих очередей сетёвки по ядрам
  • мощность ядер процессора, обрабатывающего пакеты
  • различные значения rx-usecs

Разберём их по порядку:

Размер буфера сетевой карты

    [root@centos ~]# ethtool -g eth1
    Ring parameters for eth1:
    Pre-set maximums:
    RX:		4096
    RX Mini:	0
    RX Jumbo:	0
    TX:		4096
    Current hardware settings:
    RX:		4096
    RX Mini:	0
    RX Jumbo:	0
    TX:		256

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

Есть два стула, на одном задержки точеные, на другом потери мощные.

Иными словами высокое значение RX-буфера - задержки, низкое - потери. Вообще, недавно у нас в компании была дискуссия на эту тему, о том чем всё же по факту является значение Current HW Settings RX - реальным потолком буфера пакетов или значением при превышении которого необходимо сигнализировать о том, пора обрабатывать эти пакеты очень срочно, а на самом деле они могут копиться до Pre-set maximums. Внятных аргументов я не услышал, но пометочку о том, что надо почитать документацию и исходники на эту тему себе сделал.

Пример команды для увеличения буфера:

	ethtool -G eth1 rx 4096

Распределение прерываний

Многие сетевые карты имеют несколько очередей для входящих пакетов. Каждая очередь висит на ядре/списке ядер. На многих железках из коробки, несмотря на то, что в smp_affinity_list указан список 0-$cpucount все прерывания находятся на первом ядре процессора. Обойти это можно раскидав с помощью echo все прерывания на разные ядра.

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

  • 1 процессор с гипертредингом
  • 4 реальных ядра
  • 8 виртуальных ядер
  • 4 очереди сетевой карты, которые составляют 95% работы сервера

Раскинуть их на 0, 1, 2 и 3 ядра будет не так эффективно, как на 0, 2, 4 и 6.

Пример кода (костыльный и неуниверсальный), который раскидывает 8 очередей на 8 ядер (довольно простой случай).
Строка "eth1-TxRx-" - по ней можно идентифицировать очереди сетевой карты принимающей зеркало трафика, может отличаться в зависимости от модели сетевой карты и драйвера, посмотреть как она выглядит можно в файле cat /proc/interrupts

    #!/bin/bash

    nic=eth1-TxRx-
    cpucount=$(grep -c 'model name' /proc/cpuinfo)
    grep $nic /proc/interrupts | while read irq $(eval echo cpu{1..$cpucount}) t queue t; do
      irq=${irq//:}
      /proc/irq/$irq/smp_affinity_list
      echo "${queue##*TxRx-}" > /proc/irq/$irq/smp_affinity_list
    done

Мощность ядер процессора

    [root@centos ~]# grep '' /sys/devices/system/cpu/cpu0/cpufreq/scaling_{min,cur,max}_freq 
    /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq:1600000
    /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq:1600000
    /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq:3201000

Суть видна - довольно мощный процессор работает в полсилы и даже не собирается напрягаться.

Заставить их напрячься можно так:

    #!/bin/bash
    
    cpucount=$(grep -c 'model name' /proc/cpuinfo)
    sysdir=/sys/devices/system/cpu
    for cpu in $(eval echo cpu{0..$((cpucount-1))}); do
        cat $sysdir/$cpu/cpufreq/scaling_max_freq > $sysdir/$cpu/cpufreq/scaling_min_freq
    done

Различные значения rx-usecs

Не буду плодить энтропию, так что вот ссылка на хорошую статью (правда заточенную под маршрутизаторы больше): http://habrahabr.ru/post/108240/

В кратце - можно за счёт повышения нагрузки на процессор слегка снять напряги с сетёвки уменьшая. На большинстве машин использумых в моём случае оптимальным оказалось значение 1.

	ethtool -C eth1 rx-usecs 1
Введите метки, чтобы добавить к этой странице:
Please wait 
Ищите метку? просто начните печатать.