Comments 73
У нас общая тема в настоящее время R&D, было интересно, спасибо. У меня немного потяжелее — UHD, стукнись в личку, поделимся опытом)
Опа, Лапшин, привет) Ну сам посчитай, если профиль FHD это от 9 мегабит. Если UHD — От 24. Всё зависит от клиентского устройства, обычно готовятся несколько профилей потоков, для телефона, для планшета, смарттв итд
Одна из не многих статей за последнее время для меня, которую я прочитал на одном дыхании. Большое спасибо.
Круто, но сразу же возникает вопрос: а как это вообще работало на OpenSuSE, что стало «плохо» на CentOS? Ну т.е. разве не был прописан в манифестах CFEngine аналогичный набор крутилок (которые нужно лишь перенести в манифест для CentOS)? Или у этих двух дистрибутивов насколько сильно различаются настройки ядра, что у вас это вылезло.

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

cgroups, не?

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

По поводу swap, если бы его не было, то с началом «Проблемы N2» приложения попадали бы от OOM Killer. Кроме того наличие swap даёт нам ещё одну возможность косвенным способом обнаруживать проблемы с серверами. Если в swap появились данные — это повод для расследования.
На сколько я вижу по описанию этого патча он исправляет поведение global reclaim, который (до исправлений) при запуске для одного memcg мог освобождать память другого memcg.
Во многих сценариях попадание в swap аналогично полному отказу сервиса, при этом возврат в работу из OOM может быть быстрее.
У вас похоже не совсем такой случай :)

cgroups memory.limit_in_bytes
sets the maximum amount of user memory (including file cache).
ну и такое же значение в memory.memsw.limit_in_bytes.
С помощью cgroups грубо говоря вы порежете page cache на куски и в разные его части будут попадать страницы от разных приложений, но ядро по прежнему сможет использовать под page cache всю свободную память.
Спасибо большое, очень интересно. Сталкивался с подобными проблемами, но с другим профилем нагрузки и решал в основном программным путем. Может кому интересно будет:

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

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

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

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

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

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

Второй — я не знаю что у вас на клиенте, но если там есть мобильные браузеры, то телеком провайдерам вряд ли имеет смысл держать долгие таймауты и незачем дополучать данные, RST и все, а клиенты за ними мигают часто.
Спасибо отличная статья!
Может вы сможете или попросите ваших девопс инженеров написать статью про CFEngine.
Какую версию используете, платная или Community Version, что менеджите им, как справляетесь с его однопоточностью, начали ли писать свои костыли для того, когда cf-agent не может обновиться с мастер хоста, подготовились ли к тому что прийдется перенести /var/cfengine в память?
Спасибо за отзыв.
С неразрешимыми проблемами с CFEngine мы пока что не столкнулись.
Обязательно расскажем подробно в отдельной статье.
Вы наверняка используете bonding на интерфейсах, вы не сравнивали производительность bonding драйвера и нового для centos 7 — teaming?
а зачем использовать bonding если есть teaming который вроде как новее, лучше, быстрее?
Performance overhead для bonding низкий, а для teaming очень низкий.
Мы не нашли для себя выгоду в использовании teaming, а времени на внедрение пришлось бы потратить неоправданно много, поэтому остались на bond.
хм. да там буквально одни файлы в /etc/sysconfig/network-scripts заменить на другие, и всё должно заработать.
OpenOnload только в последнем релизе начал поддерживать teaming.
в VMA по идее тоже либо уже добавили либо вот вот добавят.

вроде даже тулза есть для конвертирования, но я не пробовал access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/sec-Converting_a_Bond_to_a_Team.html
Вы же не думаете, что мы сервера руками настраиваем? :)
Есть несколько систем, которые в той или иной степени связаны с настройкой сети и для миграции на teaming необходимо подготовить все эти системы. Причём, что бы они работали с bonding и teaming одновременно.
И, повторюсь, эти трудозатраты пока ничем не оправданы.
Понятно, ну если не просто поменять то действительно лучше не трогать то что работает. Разница там по замерам совсем не большая.
интересно было бы услышать про отказоустойчивость в проектах такого масштаба.
Что используется — свой самописный велосипед, или что то из энтерпрайз продуктов?
И мой особый интерес — защита от DDoS.
Спасибо!
Это очень большая тема.
Постараемся раскрыть её в будущих статьях.
Если коротко, то используем и свои решения, и open source.
Даже неловко спрашивать такую банальщину: а все выполненные настройки как-нибудь забекапили?
учитывая что у них cfengine — думаю все настройки шли через него.
Чтобы не было вот таких казусов «Может содержать не более 8 000 правил. Классификатор пакетов Perfect filter просматривается/настраивается через ethtool -u/U flow-type. Возможно, это та же фильтрация, которая настраивается утилитой testpmd (см. выше).» предлагаю к прочтению это
День добрый.
Настривается фильтрация утилитой 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 очередям.

Здравствуйте!
Поправлю информацию про 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 ядра.

Спасибо за ваш полезный комментарий.
Теперь листаю rss хабра в надежде что появилась еще одна техническая статья от Одноклассников. :)
Особенно жду техническую статью про факап с даунтаймом ОК несколько лет назад (было на roem, но не для технарей).
А вы не смотрели/пробовали последние ядра и изменения в них (4.2)? Есть вероятность, что от Qued Spinlocks будет буст и в сетевых нагрузках.
Присоединяюсь к вопросу — почему не поиспользовать хотя бы 3.18+ — в сетевой части должен быть хороший прирост от Bulk network packet transmission, который реализован в ванильных драйверах для ixgbe и в драйверах от Intel начиная с версии 4.0.3
картинки грузятся с *.mycdn.me но если вы посмотрите IP адреса, то все они принадлежат одноклассникам. То есть CDN у них есть но свой. Все адреса расположены в москве, даже если запрос с другого конца шара сделан. То есть это не совсем CDN, а больше как вэширующие сервера.
А почему вы думаете, что если адрес в Москве, то и сервер в Москве? В общем случае, насколько я знаю, это совсем не так.

У многих российских провайдеров «юридически» айпишники московские, а по факту — могут находиться где угодно. Особенно этот факт доставляет нашей команде внутренней статистики, когда они хотят, например, четко нарисовать на карте России какое-нибудь географическое распределение — трафик по городам, число пользователей по регионам и т.п. :)
да согласен. просто я опирался не совсем на официальную базу данных. и все ип были из Москвы. то есть в России в регионах тоже есть сервера?
С CDN точек раздается статический контент, видео, фото и музыка. Точки расположены как в регионах России, так и за рубежом. Вы совершенно верно заметили домен mycdn.me. Он используется для контента, который можно балансировать с использованием DNS и отличен от основного домена (ок.ru) в целях безопасности.
Дмитрий, огромное спасибо вам и вашим коллегам за информацию, потраченные силы и время, это крайне интересно. Вы, безусловно, помогли экосистеме, поделившись опытом и находками.
Дамп сознания.
  • На CentOS/RHEL лучше тащить своё ядро из последних (3.16+, а то и 4.x, если есть лица способные чинить panic'и/регрессии)
  • При возможности ещё и собирать последние ixgbe/i40e от интела (ну или хотя бы README прочитать — он весьма полезен) и последний ethtool
  • Последняя версия set_irq_affinity.sh из того же комплекта — must have
  • Не забывайте, что irq affinity можно навешивать не только на сетевухи, но и на storage девайсы
  • Новые сетевухи умеют `adaptive-rx`/`adaptive-tx`, совсем новые `rx-usecs-high`
  • NUMA лучше не interleave'ить, а использовать по назначению. Запустите N инстансов приложения. Каждое на своей ноде. Каждой свой CPU и память, а так же сетевуху (NUMA ноду для irq affinity через можно определить от /sys/class/net/eth*/device/numa_node) и свой набор IP'шников. Далее на вышестоящем балансере (я так пологаю IPVS) считать каждую NUMA-ноду за отдельный хост
  • Для файлсерверов очень опасна /proc/sys/vm/zone_reclaim_mode — важно, чтобы оно было выставленно в ноль
  • Flow Director может приводить к сильному реордеингу. Наступали на это в кеше в Facebook'а.
  • Не забываем играться со всей магией из ethtool -k (tso, lro,[rt]xcsum, etc) и почти всегда надо задирать ring buffer'а в ethtool -g
  • Обратите внимание на топологию PCIe и скорость: lspci -t -vvv (особо важно для 40G+)
  • Проверить, что ioatdma/DCA включено и работает
  • Всё что выходит за пределы 40G — надо переходить на Netmap/DPDK/etc
  • Jumboframes наружу конечно нельзя, но вот внутри сети лучше включить
  • Если у вас есть HTTPS, то всё становится сложнее, Netflix опять же похачил (FreeBSD'шное) ядро, чтобы то умело делать sendfile(2) с AES
  • Уже не совсем в тему оптимизации производительности, а скорее ускореения пользователей — стоит поиграться с TCP congestion алгоритмами (Netflix написали свой оптимизированый для видео и их склиентов: cc_netflix) — щас говорят ещё модно CDG (упаковать его в dkms и проверить на паре фронтэндов займёт пол дня)
  • Если бы у вас были интерактивные штуки, а не видео, то было бы интересно поиграться с buffer bloat (sch_fq, tsq, bql, etc).
  • В ту же степь: net.ipv4.tcp_slow_start_after_idle=0
  • В userspace (оптимизация webserver'а) можно быстро получить выхлоп от нового OpenSSL 1.0.2 и Haswell (там переписан TLS RSA handshake на AVX2)
  • Новый pcre с jit (или замена его на re2)
  • glibc malloc (почти ptmalloc) заменить на jemalloc
Спасибо за ваш комментарий, Алексей.
Ради одного вашего комментария стоило писать эту статью.

Отвечу по пунктам:
  • Новое ядро пробовали пока только на видео раздаче, выигрыша не получили, но это скорее связано с (пока) неопределённой проблемой высокого softirq. Тоже самое с TCP congestion алгоритмами и tcp_slow_start_after_idle=0.
  • В стоковом ядре драйвер довольно новый, хоть и отличается от out-of-tree. Тем не менее мы их тоже тестили в рамках борьбы с softirq и тоже не помогло.
  • Вижу, что вы в set_irq_affinity учитываете NUMA и конфигурите XPS заодно — это круто. Мы используем модифицированный set_irq_affinity, который настраивает все очереди всех поднятых интерфейсов сразу + все прерывания дисковых контроллеров LSI и распределяем по очереди на все ядра по кругу. Но не учитываем NUMA. Что касается XPS, то на ixgbe и mlx4 он конфигурится автоматом. Надеюсь впилим и NUMA со временем.
  • Адаптивную модерацию мы выключаем (на i40e, например), т.к. она заботится о latency, а нам нужен был throughput.
  • NUMA лучше не интерливить, трудно не согласиться :) Пока приложение не готово, но мы работаем в этом направлении. А вы делали какие-то сравнительные тесты по NUMA — какой выигрыш на какой-нибудь активной раздаче?
  • zone_reclaim_mode умышленно не трогал.
  • Про OOO в Flow Director тоже читал и собираюсь упомянуть на Highload++, а то сам Intel про это как-то не упоминает.
  • Ринг буферы задраны и оффлоадинги включены. На самом деле, конечно, в статье далеко не все использованые оптимизации упомянуты, только то что было новым для нас.
  • На скорость PCIe уже наталкивались, теперь тщательно проверяем.
  • С ioatdma был казус в Centos 7 bugs.centos.org/view.php?id=8778, а Red Hat как-то вообще говорит, что он не нужен access.redhat.com/articles/879293.
  • Для Netmap/DPDK надо писать свой TCP stack. Для mTCP перепиливать приложение. Fastsocket ещё не пробовали, но планируем. OpenOnload только с Solarflare, которого у нас нет. Было бы интересно узнать про success story использования user-space tcp с какими-то Java HTTP серверами (вроде lighttpd в который впилили mTCP сами разработчики mTCP).
  • Jumboframes тоже есть в планах.
  • Malloc менаем на tcmalloc.


Ещё раз спасибо за прекрасную подборку заклинаний! :)
по поводу «OpenOnload только с Solarflare, которого у нас нет». Так а Mellanox VMA то используете?
А подскажите как использовать set_irq_affinity.sh
Я при старте программы например использую пару ядер (скажем номер 3 и номер 4) для spinning. Там мне прерывания не нужны. Я хочу перенести прерывания с этих ядер на ядро 0. Могу я как-то для этой задачи этот скрипт приспособить?

И ещё стоит ли полностью отключать ipv6 если ipv6 не используется? Так как здесь написано access.redhat.com/solutions/8709
У set_irq_affinity.sh нет готового функционала для игнорирования каких-то ядер, но скрипт достаточно простой, что бы заложить туда любую необходимую вам логику.

Стоит или не стоит отключать ipv6 зависит от того используете вы его или нет.
https://patchwork.ozlabs.org/patch/671069/ — Google предложил готовый патч добавляющий BBR congestion control алгоритм, сами используют на google.com и youtube.com (prooflink: https://twitter.com/igrigorik/status/777559295315501057)
Основной конкурент Mellanox — Solarflare вполне себе поддерживает Accelerated RFS. Причём помоему давно.
Так и называется Solarflare Accelerated RFS.

Implement SARFS; Solarflare Accelerated Receive Flow Steering
(disabled by default) This inserts hardware RX filters in order to direct
flows back to the same CPU where the user-land process is transmitted. This
should help cache locality.
This feature can be used when Accelerated RFS is not available in the
currently running kernel, and if ARFS is in use will be disabled.
To enable SARFS, set the «sarfs_sample_rate module» parameter to non-zero.
20 is recommended.
In addition, some form of XPS is needed for SARFS to function correctly. The
easiest way to do this is to enable Solarflare XPS by setting the module
parmaeter «sxps_enabled=1»
Alternatively if your kernel supports it you can enable XPS by following the
instructions at:
www.kernel.org/doc/Documentation/networking/scaling.txt
Спасибо, у нас нет опыта использования Solarflare, поэтому в статье они не упомянуты.
Only those users with full accounts are able to leave comments. Log in, please.