image

До недавнего времени в Одноклассниках в качестве основного Linux-дистрибутива использовался частично обновлённый OpenSuSE 10.2. Однако, поддерживать его становилось всё труднее, поэтому с прошлого года мы перешли к активной миграции на CentOS 7. На подготовительном этапе перехода для CentOS были отработаны все внутренние процедуры, подготовлены конфиги и политики настройки (мы используем CFEngine). Поэтому сейчас во многих случаях миграция с одного дистрибутива на другой заключается в установке ОС через kickstart и развёртывании приложения с помощью системы деплоя нашей разработки — всё остальное осуществляется без участия человека. Так происходит во многих случаях, хотя и не во всех.

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

Вкратце об их конфигурации:
  • 4 x 10 Гбит к пользователям
  • 2 x 10 Гбит к хранилищу
  • 256 Гбайт RAM — кэш в памяти
  • 22 х 480 Гбайт SSD — кэша на SSD
  • 2 х E5-2690 v2


Несколько метрик, характеризующих раздачу видео:
  • 600 Гбит/сек. — общая пиковая скорость отдачи видео
  • 220М просмотров видео в день
  • 600К одновременно просматриваемых видео


Проблема 1 — сильный рост CPU system time


image

Вскоре после запуска первого сервера начала сильно расти нагрузка на процессор по system time.
В это же время в top было видно множество migration и ksoftirqd процессов. Сначала мы попробовали крутить настройки ядра. Что нам не помогло:
  • увеличение sched_migration_cost
  • отключение transparent_hugepage
  • увеличение vfs_cache_pressure
  • отключение NUMA

При очередном росте нагрузки perf top показал 50% нагрузки на isolate_freepages_block. Само по себе название вызова нам, к сожалению, ничего не говорит. Но вот слово freepages несколько смутило, т.к. свободной памяти на сервере было около 45 Гбайт. Из своего опыта мы уже знали, что если на сервере много свободной памяти, а ядро всё равно жалуется на его нехватку (иногда это выражается в запуске OOM killer), то, скорее всего, проблема во фрагментации. Сброс дискового кеша (echo 3 > /proc/sys/vm/drop_caches) моментально исцелял сервер, что только подтверждало наши предположения.

Фрагментация памяти — нередкая проблема (и характерна не только для Linux), и в ядро регулярно вносятся изменения для борьбы с ней. Одним из виновников фрагментации является само ядро, точнее дисковый кеш, который нельзя ни отключить, ни ограничить в объёме. Это не значит, что фрагментация в нашем случае была вызвана именно дисковым кешем, но точные причины были не так важны. Важнее было решение — дефрагментация. Такой механизм есть в ядре, но очевидно, что он не справлялся (либо вместо него запускалось высвобождение памяти — global reclaim). Дефрагментация запускается только тогда, когда свободная память опускается ниже определённой отметки (zone watermark), и в нашем случае это происходило слишком поздно. Единственный способ заставить её запускаться раньше — это повысить min_free_kbytes через sysctl. Данный параметр говорит ядру стараться держать часть памяти свободной, а чтобы удовлетворить это требование, ему приходится запускать дефрагментацию раньше. В нашем случае хватило значения в 1 Гбайт.

Проблема 2 — уход в swap


Для начала стоит упомянуть, что мы используем vm.swappiness=0, так как точно знаем, что для нас своп — это зло. Итак, на сервере около 45 Гбайт свободной памяти и всё же он периодически уходит в своп. Как такое возможно? Для начала стоит напомнить, что память в Linux — это не один большой кусок.
  • Память делится на ноды: один физический процессор — одна нода.
  • Каждая нода делится на зоны (представление для 64-битных систем) — ZONE_DMA (0-16 Мбайт), ZONE_DMA32 (0-4 Гбайт), ZONE_NORMAL (4+ Гбайт).
  • Каждая зона делится на области памяти размером степеней двойки (order of 2), т.е. 20*PAGE_SIZE, 21*PAGE_SIZE...210*PAGE_SIZE (текущее распределение можно посмотреть в /proc/buddyinfo). Отсутствие свободных областей большого размера — это и есть фрагментация, о которой мы говорили в предыдущем разделе.


Сначала мы опять винили фрагментацию, но дальнейшее увеличение min_free_kbytes, а также увеличение vfs_cache_pressure нам не помогло. Пришлось познакомиться с утилитой numastat (numastat -m < PID >).

Но сначала ещё одно отступление про работу приложения раздачи видео. На сервере замонтирован tmpfs (занимает почти всю память), на котором приложение создаёт 1 файл и использует его в качестве кеша.

Что же мы увидели в выводе numastat? А то, что различные типы памяти распределены между нодами крайне неравномерно:
Per-node process memory usage (in MBs) for PID 7781 (java)
Node 0 Node 1 Total
Huge 0 0 0
Heap 0.20 0.14 0.34
Stack 118.82 137.87 256.70
Private 80200.73 123323.81 203524.55
Total 80319.76 123461.82 203781.58
Per-node system memory usage (in MBs):
Node 0 Node 1 Total
MemTotal 131032.75 131072.00 262104.75
MemFree 1228.93 639.84 1868.78
MemUsed 129803.82 130432.16 260235.98
Active 23224.13 121073.42 144297.55
Inactive 101138.88 3753.98 104892.85
Active(anon) 1690.50 120997.86 122688.36
Inactive(anon) 79528.66 3560.95 83089.61
Active(file) 21533.63 75.57 21609.20
Inactive(file) 21610.21 193.03 21803.24
Unevictable 0 0 0
Mlocked 0 0 0
Dirty 0.11 0.02 0.13
Writeback 0 0 0
FilePages 122397.46 124295.47 246692.93
Mapped 78436.03 122947.26 201383.29
AnonPages 1966.62 532.02 2498.64
Shmem 79251.21 123964.70 203215.90
KernelStack 2.44 2.57 5.01
PageTables 158.62 252.29 410.91
NFS_Unstable 0 0 0
Bounce 0 0 0
WritebackTmp 0 0 0
Slab 1801.95 1932.29 3734.23
SReclaimable 1653.13 1818.79 3471.92
SUnreclaim 148.82 113.49 262.31
AnonHugePages 1856.00 498.00 2354.00
HugePages_Total 0 0 0
HugePages_Free 0 0 0
HugePages_Surp 0 0 0

За распределение памяти между нодами отвечает технология NUMA, и она не может равномерно распределить 1 файл в tmpfs между нодами. Запуск приложения в режиме interleave (numactl —interleave=all, равномерное распределение памяти приложения между нодами) решило нашу проблему.

Проблема 3 — неравномерное распределение нагрузки по ядрам


Пожалуй, все, кто работал с большим трафиком, сталкивались с проблемой распределения прерываний между ядрами процессоров. Чаще всего проблема исследуется и решается так (здесь приведены все шаги, но не обязательно, что вы столкнётесь с каждым):

  1. CPU0 нагружен больше остальных (особенно много softirq). Проблема в том, что у сетевого адаптера только одна очередь, она работает на одном прерывании, которое работает на одном ядре. Настраиваем очереди сетевой карты (раньше это делалось через опции драйвера, сейчас через ethtool -l/-L). Например, для 1 Гбит карт Intel очередей может быть 8, для 10 Гбит карт — до 128.
  2. Нагрузка не перераспределилась. Очередей много, прерываний много, но все на CPU0. Включаем демон irq_balancer.
  3. Нагрузка распределяется не равномерно. Ну что же, автоматика не идеальна, нужен ручной режим. Находим в сети популярный set_irq_affinity (или его аналог) и запускаем — так мы настроили RSS (receive side scaling) — первую технологию из увлекательного документа от разработчиков ядра https://www.kernel.org/doc/Documentation/networking/scaling.txt.
  4. Нагрузка ложится только на 8 первых ядер, если у нас всего 8 очередей, или нагрузка ложится только на 16 ядер, даже если очередей больше.
    Эээ?.. Об этом расскажу подробнее.

Для начала разберёмся с ограничением в 16 ядер и с тем, почему Intel позволяет делать много очередей (на 10 Гбит), а загружает, в основном, первые 16.

Волшебная цифра 16 — это максимальное количество очередей, на которое может распределить трафик RSS. Длина хеша RSS-индекса нормальная, но используются только последние 4 бита, поэтому максимальное количество очередей, которое он может выдать — 16. Это ограничение самой технологии и с ним ничего сделать нельзя.

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

Во-вторых, у карт есть Flow director.

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

Flow director

Flow director, судя по доке Intel, работает в 2 режимах — Signature Filter (он же ATR — Application Targeted Receive) и Perfect filter. Flow director не воспринимает не-IP пакеты, туннелированные пакеты и фрагментированные пакеты. Можно посмотреть статистику попавших/не попавших пакетов в flow director: ethtool -S ethN|grep fdir

Perfect filter (ntuple)

Может содержать не более 8 000 правил. Классификатор пакетов Perfect filter просматривается/настраивается через ethtool -u/U flow-type.

Signature Filter

Может содержать не более 32 000 правил. Согласно интернетам, ATR запоминает, в какую очередь (и на каком процессоре) _ушёл_ SYN пакет и направляет приходящие пакеты этого потока через ту же очередь.

During transmission of a packet (every 20 packets by default), a hash is calculated based on the 5-tuple. The (up to) 15-bit hash result is used as an index in a hash lookup table to store the TX queue. When a packet is received, a similar hash is calculated and used to look up an associated Receive Queue. For uni-directional incoming flows, the hash lookup tables will not be initialized and Flow Director will not work. For bidirectional flows, the core handling the interrupt will be the same as the core running the process handling the network flow.

[1]

Т.е., для входящего пакета будет использоваться та же очередь, в которую был помещён первый исходящий SYN, или каждый 20 пакет (конфигурация этого числа в новом драйвере отсутствует, а в старых называлась AtrSampleRate). Если пакет не попадает в ATR, то он классифицируется по RSS (т.е. на первые 16 ядер). Последний факт и навёл нас на правильный путь. Посмотрев статистику flow director через ethtool -S ethN | grep fdir, мы увидели большое количество fdir_miss. Т.е. пакеты не обрабатывались в ATR, а проваливались до RSS. В результате большая часть нагрузки ложилась на первые 16 ядер. Разработчики драйвера ответили (https://sourceforge.net/p/e1000/bugs/464/), что у нас слишком много потоков, поэтому нам лучше использовать софтверный аналог этой технологии — RPS.

Раз оно нам не помогает, то лучше отключить совсем — для этого делаем ethtool -k ethN ntuple on. Эта команда не только выключает ATR, но и включает Perfect filter, который, однако, без правил совсем никак не помогает, но и не мешает.

RPS (receive packet steering)

Чисто софтверный механизм. Технология номер 2 (после RSS) в уже упомянутом документе от разработчиков ядра — scaling.txt.

Прерывания не трогает вообще (можно распределить статически или через irq_balancer).

Изначально этот механизм был создан для распределения нагрузки по ядрам на картах с одной очередью. Однако, как мы теперь понимаем, он также хорош, когда количество очередей и ядер больше 16. Суть этого механизма в том, что независимо от того, в какую очередь пришёл пакет, обрабатываться он будет на ядре, выбранном по хешу. Хеш RPS, в отличие от RSS, может выдать результат больше 16 (т.к. использует его целиком), поэтому задействуются все ядра (если быть точнее, то в файле rps_cpus можно указать, какие конкретно ядра разрешено использовать).

Т.к. эта технология использует ресурсы процессора, то, конечно, есть некоторый оверхед, но он незначительный, т.к. самую тяжёлую операцию — расчёт хеша — всё равно делает карта. Не останавливаясь на достигнутом, продолжаем читать уже полюбившийся scaling.txt и находим там RFS.

RFS (receive flow steering)

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

Разница хорошо видна на диаграммах[2]:
RPS RFS
RPS RFS


Accelerated RFS

Чтобы закончить разбор технологий из scaling.txt, стоит также рассказать и про Accelerated RFS. Кто и что тут ускоряет? В случае с RFS работу по распределению пакетов по нужным ядрам в зависимости от хеша пакета выполняет центральный процессор. А в случае с Accelerated RFS этим занимается сетевая карта, снимая нагрузку с процессора. Но из известных нам сетевых адаптеров эту технологию на сегодняшний день поддерживает только Mellanox.

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

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

Проблема 4 — большое количество broken pipe


Регулярно появление ошибок broken pipe наблюдалось в приложении ещё на OpenSuSE, но с переходом на CentOS было принято решение положить этому конец. Тогда мы ещё не знали, сколько времени это займёт, ведь “пощупать” эти ошибки очень сложно.

Broken pipe — это ошибка, которая возникает, когда приложение не может записать данные в pipe. На одном конце pipe находится приложение, на другом — файл или соединение. Если пропадёт диск, на котором находится файл, или компьютер, с которым установлено соединение, то попытка записи в pipe завершится ошибкой broken pipe. В ходе изучения дампов трафика было замечено, что клиенты не просто пропадают, а закрывают соединения в ускоренном режиме (half-duplex tcp close sequence), что само по себе не является чем-то некорректным. Так почему же некоторые наши клиенты закрывают соединения не получив все данные и даже не пытаясь нормально закрыть соединение? Откуда такое безразличие к запрошенным данным и спешка? Дальнейшее расследование происходило исключительно эмпирическим путём, т.к. поймать такие эти ошибки на стороне клиентов и понять, что у них происходит, было бы слишком трудоёмким занятием. Поэтому поиск решения занял много времени.

Наиболее вероятная причина — это «packet reordering» (http://en.wikipedia.org/wiki/Out-of-order_delivery), хотя доказательств нет. Т.к. некоторые проблемы, описанные в данной статье, решались параллельно, то оказалось, что включение RFS резко снижает количество broken pipe.

image

Второй фактор, который повлиял на снижение количества ошибок — это interrupt coalescing. Что это за зверь, рассказывается в следующей главе.

Проблема 5 — большое количество прерываний


Трафик бывает разный, и если фанаты Counter Strike крайне болезненно относятся к высокому latency, то для любителей торрентов (и любых других приложений, работающих с большим количеством трафика) куда важнее пропускная способность. Что касается раздачи видео, то это очень много трафика (десятки гигабит с сервера) и очень много пакетов (миллионы), а значит очень много процессорной нагрузки типа softirq. Во время тестов при пиковой нагрузке на сервер softirq мог достигать 50% от всей нагрузки на процессор.

Настройка, которая уменьшает нагрузку на CPU, — мечта любого админа. В данном случае нам помог interrupt coalescing, который настраивается через ethtool -c/-C. При увеличении параметров interrupt coalescing прерывания генерируются реже — не на каждый пакет, а сразу на пачку.

image

Стоит отметить, что нагрузка softirq растёт нелинейно, так что чем больше трафик, тем сильнее эффект.
Описание параметров:
  • [rx|tx]-usecs — максимальное время в микросекундах между получением пакета и генерированием прерывания
  • [rx|tx]-frames — количество пакетов, после получения которого генерируется прерывание
  • *-irq — то же самое для обновления статуса при отключенных прерываниях
  • *-[low|high] — то же самое для адаптивного режима


Итоги


В результате проделанных работ мы получили:
  1. дистрибутив, поддерживаемый до 2024 года [3]
  2. снижение количества ошибок broken pipe в 40 раз
  3. повышение производительности серверов (один сервер способен обработать 50 Гбит в секунду)
  4. опыт работы с различными новыми технологиями (а также политики CFEngine для их автоматического конфигурирования)

А всё это вместе позволит нам в будущем отдать с одного сервера ещё больше трафика.

Постскриптум


В заключение хочется сказать спасибо нашим разработчикам, которые помогали в работе и оптимизировали приложение, а также коллегам-администраторам, благодаря которым у меня было время на все эти изыскания. Самые сложные задачи дают больше всего знаний, опыта и удовлетворения. Хотя и треплют нервы.

Сноски


  1. https://networkbuilders.intel.com/docs/network_builders_RA_packet_processing.pdf
  2. https://wiki.freebsd.org/201305DevSummit/NetworkReceivePerformance/ComparingMutiqueueSupportLinuxvsFreeBSD
  3. https://wiki.centos.org/About/Product

Комментарии (57)


  1. DimaSmirnov
    03.09.2015 12:29
    +35

    Без сарказма, отличная работа.


    1. dmitrysamsonov
      03.09.2015 16:37
      +4

      Спасибо, Дмитрий. Рад, что вам понравилось.


      1. DimaSmirnov
        06.09.2015 17:37

        У нас общая тема в настоящее время R&D, было интересно, спасибо. У меня немного потяжелее — UHD, стукнись в личку, поделимся опытом)


        1. erlyvideo
          06.09.2015 19:26

          Какой у вас битрейт?


          1. DimaSmirnov
            06.09.2015 20:48
            +1

            Опа, Лапшин, привет) Ну сам посчитай, если профиль FHD это от 9 мегабит. Если UHD — От 24. Всё зависит от клиентского устройства, обычно готовятся несколько профилей потоков, для телефона, для планшета, смарттв итд


  1. SyCraft
    03.09.2015 14:30
    +7

    Звучит очень круто! большой респект


    1. dmitrysamsonov
      03.09.2015 16:40
      +1

      Спасибо.


  1. baltazorbest
    03.09.2015 14:36
    +13

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


    1. dmitrysamsonov
      03.09.2015 16:43
      +1

      Спасибо. Редактора старались :)


  1. slava_k
    03.09.2015 14:49
    +5

    Большое спасибо за то, что поделились опытом!


    1. dmitrysamsonov
      03.09.2015 16:43
      +1

      Спасибо, будем продолжать.


  1. evg_krsk
    03.09.2015 16:08
    +1

    Круто, но сразу же возникает вопрос: а как это вообще работало на OpenSuSE, что стало «плохо» на CentOS? Ну т.е. разве не был прописан в манифестах CFEngine аналогичный набор крутилок (которые нужно лишь перенести в манифест для CentOS)? Или у этих двух дистрибутивов насколько сильно различаются настройки ядра, что у вас это вылезло.

    Или же вы просто решили заодно с миграцией и оптимизировать использование ресурсов, чиня существующие на OpenSuSE проблемы?


    1. dmitrysamsonov
      03.09.2015 16:52

      Спасибо.
      Часть описанных проблем не проявлялась в OpenSuSE ввиду его возраста. Часть проблем и оптимизаций действительно были проведены заодно.
      Что касается политик CFEngine, то процесс его внедрения у нас в компании ещё не завершён (и мы обязательно напишем подробно о том как это происходит), поэтому не все инструменты были готовы. Кроме того, переход на другой дистрибутив так же требует доработки политик.


  1. erlyvideo
    03.09.2015 16:11

    > дисковый кеш, который нельзя ни отключить, ни ограничить в объёме.

    cgroups, не?

    И второй вопрос: зачем вообще вам swap на видеостримере?


    1. dmitrysamsonov
      03.09.2015 17:09
      +1

      Не нашёл такой возможности в cgroups. Расскажите поподробнее.

      По поводу swap, если бы его не было, то с началом «Проблемы N2» приложения попадали бы от OOM Killer. Кроме того наличие swap даёт нам ещё одну возможность косвенным способом обнаруживать проблемы с серверами. Если в swap появились данные — это повод для расследования.


      1. erlyvideo
        03.09.2015 17:10
        +1

        подробно к сожалению не отвечу.

        Возможно поможет: lwn.net/Articles/516431


        1. dmitrysamsonov
          03.09.2015 17:19

          На сколько я вижу по описанию этого патча он исправляет поведение global reclaim, который (до исправлений) при запуске для одного memcg мог освобождать память другого memcg.


      1. catharsis
        15.09.2015 15:09

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

        cgroups memory.limit_in_bytes
        sets the maximum amount of user memory (including file cache).
        ну и такое же значение в memory.memsw.limit_in_bytes.


        1. dmitrysamsonov
          15.09.2015 15:51
          +1

          С помощью cgroups грубо говоря вы порежете page cache на куски и в разные его части будут попадать страницы от разных приложений, но ядро по прежнему сможет использовать под page cache всю свободную память.


  1. laphroaig
    03.09.2015 16:49
    +2

    Спасибо большое, очень интересно. Сталкивался с подобными проблемами, но с другим профилем нагрузки и решал в основном программным путем. Может кому интересно будет:

    Неравномерное распределение нагрузки по ядрам может происходить по разным причинам. На linux одним из самых эффективных решений — это фиксированный пул потоков, в каждом из котором свой цикл epoll, а слушающий сокет дублируется и может акцептиться в любом из потоков. После акцепта новый сокет продолжает обрабатываться в том же цикле потока. Все это работает очень шустро, т.к. нет оверхеда на всевозможные очереди и пр. Однако здесь есть подводный камень — по каким-то причинам, приоритет при акцепте, отдается потоку с меньшим id и в результате одни из потоков становиться более нагруженным. Если сервер работает в режиме “запрос на подключение”, то особых проблем не возникает даже на больших нагрузках, а вот если сервер работает с большим числом постоянных подключений при перезапуске будет сюрприз. Несколько сот тысяч клиентов одновременно пытается подключиться, и почти всех практически моментально заакцептит одно ядро, а у остальных ядер будет возможность подхватывать только новые подключения, в то время как первое будет перегружено. В этом случае имеет смысл сделать отдельный поток для акцептора и каким либо образом распределять сокеты по остальным потокам в зависимости от нагрузки.

    Broken pipe может возникать при попытке записать в разорванное соединение. Например, в синхронном сервере (ответ на запрос формируется сразу в том же потоке) во время обработки запроса клиент закрывает соединение, т.е. к моменту вызова write клиент уже отключился, но вы не знаете об этом и получаете при записи Broken pipe. Вы конечно же узнаете о том, что сокет закрыт при следующем вызове epoll. В асинхронных серверах broken pipe, случаются реже, но также возможны. Если Broken pipe слишком много, то возможно, epoll цикл реализован не оптимально, например происходит попытка записать большой объем данных кусками в сокет без вызова epoll.


    1. Bloof
      03.09.2015 18:57
      +3

      … фиксированный пул потоков, в каждом из котором свой цикл epoll, а слушающий сокет дублируется и может акцептиться в любом из потоков.

      В приложении раздачи мы используем epoll и обертку над нативными сокетами one-nio. Принимает соединения один тред-акцептор, однако читают/пишут данные уже несколько тредов-селекторов. Число селекторов равно числу ядер на сервере, причем каждый селектор привязан к своему ядру через thread affinity.
      … происходит попытка записать большой объем данных кусками в сокет без вызова epoll.

      Селектор неблокирующе пишет в сокет только один раз, затем снова использует epoll.

      Про устройство сервера раздачи и детали приложения также планируется статья.


      1. Godless
        03.09.2015 22:21
        +1

        с нетерпением будем ждать.
        ps: почему то думалось, что one-nio это для c/c++, а оказалось чуточку не так))


  1. robert_ayrapetyan
    03.09.2015 19:02

    Подскажите как крутить interrupt coalescing на FreeBSD


    1. dmitrysamsonov
      04.09.2015 12:21
      +1

      Мы не используем FreeBSD.


  1. mrjj
    03.09.2015 20:15
    +1

    Очень круто, много нового узнал, спасибо!


    1. dmitrysamsonov
      04.09.2015 12:21

      Спасибо.


  1. mrjj
    03.09.2015 20:33

    по поводу broken pipes

    Первый вариант что пришел мне в голову — вы по каким-то причинам сами не до конца корректно обрабатываете FIN-shake или отвечаете на него медленно и получаете RST по таймауту.

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


  1. smartlight
    03.09.2015 20:45
    +6

    Спасибо отличная статья!
    Может вы сможете или попросите ваших девопс инженеров написать статью про CFEngine.
    Какую версию используете, платная или Community Version, что менеджите им, как справляетесь с его однопоточностью, начали ли писать свои костыли для того, когда cf-agent не может обновиться с мастер хоста, подготовились ли к тому что прийдется перенести /var/cfengine в память?


    1. dmitrysamsonov
      04.09.2015 12:24

      Спасибо за отзыв.
      С неразрешимыми проблемами с CFEngine мы пока что не столкнулись.
      Обязательно расскажем подробно в отдельной статье.


  1. nucleusv
    04.09.2015 00:00
    +1

    Вы наверняка используете bonding на интерфейсах, вы не сравнивали производительность bonding драйвера и нового для centos 7 — teaming?


    1. dmitrysamsonov
      04.09.2015 12:43

      Используем bonding.
      Производительность не сравнивали.


  1. derwin
    04.09.2015 06:10
    +4

    интересно было бы услышать про отказоустойчивость в проектах такого масштаба.
    Что используется — свой самописный велосипед, или что то из энтерпрайз продуктов?
    И мой особый интерес — защита от DDoS.
    Спасибо!


    1. dmitrysamsonov
      04.09.2015 19:22
      +1

      Это очень большая тема.
      Постараемся раскрыть её в будущих статьях.
      Если коротко, то используем и свои решения, и open source.


  1. lightman
    04.09.2015 07:16
    +2

    Даже неловко спрашивать такую банальщину: а все выполненные настройки как-нибудь забекапили?


    1. gtbear
      04.09.2015 11:56

      учитывая что у них cfengine — думаю все настройки шли через него.


      1. dmitrysamsonov
        04.09.2015 12:35

        Совершенно верно — CFEngine + git.


  1. RAMAZAN
    04.09.2015 07:35

    Очень крутая статья, было интересно читать.


    1. dmitrysamsonov
      04.09.2015 19:57
      +1

      Спасибо.


  1. pavelodintsov
    04.09.2015 12:15
    -2

    Чтобы не было вот таких казусов «Может содержать не более 8 000 правил. Классификатор пакетов Perfect filter просматривается/настраивается через ethtool -u/U flow-type. Возможно, это та же фильтрация, которая настраивается утилитой testpmd (см. выше).» предлагаю к прочтению это


  1. T0R
    04.09.2015 18:52
    +1

    День добрый.

    Настривается фильтрация утилитой testpmd

    testpmd — это не утилита, это sample application из фреймворка intel dpdk, в котором показано, как программисту работать с pmd (poll mode driver). К ядерному драйверу (например ixgbe) не имеет отношения. Для ядерных драйверов есть ethtool.
    Может содержать не более 8 000 правил.

    зависит от регистра PBALLOC. Максимальное значение для perfect — 8k — 2, при этом из 512 кбайт пакетного буфера на порт будет заимствовано 256кбайт. Чем это чревато — потерей пакетов в определенных ситуациях (например сильные всплески мелкопакетного трафика, при нехватке dma).
    Может содержать не более 32 000 правил.

    Не более 32k — 2 при максимальном PBALLOC
    ATR запоминает, в какую очередь (и на каком процессоре) _ушёл_ SYN пакет и направляет приходящие пакеты этого потока через ту же очередь.

    ATR — это видимо какая-то софтовая часть. Signature filter работает не так. Он просто роутит по очередям по 13-15 (в зависимости от PBALLOC) least significant bits от хеша по packet tuple. Сам fpga чипа не может следить за проходящими syn и создавать динамически фильтры.
    И да, в вышей ситуации, когда у вас 16+ ядер при 4-х 10G портах, почему бы не полагаться на RSS, ведь можно балансить по 4*16 очередям.


    1. dmitrysamsonov
      04.09.2015 19:56
      +2

      Здравствуйте!
      Поправлю информацию про testpmd.
      Проблема с регистром PBALLOC в том, что его нельзя изменить в драйвере ixgbe 3.15.1-k из состава CentOS 7 (я писал об этом в багрепорте, который упоминается в статье). Более новых драйверов тогда ещё не было выпущено.
      В любом случае, Flow director не подходит для нашей задачи.

      Про ATR сам Intel пишет так:

      The Intel® Ethernet Flow Director and the Application Target Routing (ATR) service found in Intel’s Ethernet controllers, is an advanced network offload technology that provides the benefits of parallel receive processing in multiprocessing environments that automatically steer incoming
      network data to the same core on which its application process resides. Intel Ethernet Flow Director and ATR preserve the Traffic Flow>Core (Application) relationship. As a result, Intel Ethernet Flow Director and ATR can significantly lower latency and improve CPU usage.

      Т.е. это аналог RPS+RFS.

      Про RSS: У нас была вариант сократить количество очередей до 10 и он подходил для WAN, т.к. там 4 карты (при 40 ядрах), но для LAN такой вариант уже не сработал бы, т.к. там всего 2 карты и нагрузка бы легла только на 32 ядра.

      Спасибо за ваш полезный комментарий.


  1. Nastradamus
    04.09.2015 20:40
    +2

    Теперь листаю rss хабра в надежде что появилась еще одна техническая статья от Одноклассников. :)
    Особенно жду техническую статью про факап с даунтаймом ОК несколько лет назад (было на roem, но не для технарей).


    1. dmitrysamsonov
      04.09.2015 20:41
      +2

      Зрите в корень — осталось не долго.


  1. stalkerg
    08.09.2015 12:32
    +1

    А вы не смотрели/пробовали последние ядра и изменения в них (4.2)? Есть вероятность, что от Qued Spinlocks будет буст и в сетевых нагрузках.


    1. dmitrysamsonov
      09.09.2015 10:17

      Ещё не пробовали.


      1. perestrelka
        09.09.2015 11:47

        Присоединяюсь к вопросу — почему не поиспользовать хотя бы 3.18+ — в сетевой части должен быть хороший прирост от Bulk network packet transmission, который реализован в ванильных драйверах для ixgbe и в драйверах от Intel начиная с версии 4.0.3


  1. RUnnerTomsk
    08.09.2015 14:20
    +2

    Шикарная работа! Супер!


    1. dmitrysamsonov
      09.09.2015 10:18

      Спасибо.


  1. sidorvm
    09.09.2015 03:51

    а почему бы вам не начать использовать CDN для фото и видео?


    1. 23derevo
      09.09.2015 12:32
      +2

      а почему вы думаете, что Одноклассники не используют CDN?


      1. sidorvm
        09.09.2015 12:52

        картинки грузятся с *.mycdn.me но если вы посмотрите IP адреса, то все они принадлежат одноклассникам. То есть CDN у них есть но свой. Все адреса расположены в москве, даже если запрос с другого конца шара сделан. То есть это не совсем CDN, а больше как вэширующие сервера.


        1. 23derevo
          09.09.2015 12:59
          +1

          А почему вы думаете, что если адрес в Москве, то и сервер в Москве? В общем случае, насколько я знаю, это совсем не так.

          У многих российских провайдеров «юридически» айпишники московские, а по факту — могут находиться где угодно. Особенно этот факт доставляет нашей команде внутренней статистики, когда они хотят, например, четко нарисовать на карте России какое-нибудь географическое распределение — трафик по городам, число пользователей по регионам и т.п. :)


          1. sidorvm
            09.09.2015 13:20

            да согласен. просто я опирался не совсем на официальную базу данных. и все ип были из Москвы. то есть в России в регионах тоже есть сервера?


            1. privatelv
              09.09.2015 13:47
              +3

              С CDN точек раздается статический контент, видео, фото и музыка. Точки расположены как в регионах России, так и за рубежом. Вы совершенно верно заметили домен mycdn.me. Он используется для контента, который можно балансировать с использованием DNS и отличен от основного домена (ок.ru) в целях безопасности.


              1. sidorvm
                10.09.2015 09:06

                Спасибо :)


  1. Snowbird
    09.09.2015 17:24
    +3

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


    1. dmitrysamsonov
      09.09.2015 17:48

      Спасибо, Константин.