Optimizing web servers for high throughput and low latency by Dropbox.tech
Разбор всех компонентов Linux машины участвующих в обработке трафика и методы оптимизаций их производительности, от типов CPU и до алгоритмов сжатия.
tags: #linux #performance #network #tuning
Разбор всех компонентов Linux машины участвующих в обработке трафика и методы оптимизаций их производительности, от типов CPU и до алгоритмов сжатия.
tags: #linux #performance #network #tuning
dropbox.tech
Optimizing web servers for high throughput and low latency
👍2
CPU Utilization is Wrong by Brendan Gregg
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается ориентироваться на показатель IPC (instructions per cycle), доступный в
tags: #linux #performance #metrics #cpu
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается ориентироваться на показатель IPC (instructions per cycle), доступный в
perf stat
, atop
, perf
коллектор в node_exporter
, etc.tags: #linux #performance #metrics #cpu
👍3✍1
A Complete Guide of 'ss' Output Metrics by Mark Zhu
Самое подробное описание использования утилиты
tags: #network #linux #troubleshooting #tooling
Самое подробное описание использования утилиты
ss
что я встречал.tags: #network #linux #troubleshooting #tooling
Mark Zhu's Blog
A Complete Guide of 'ss' Output Metrics - TCP Connection Inspecting Tool
Understanding metrics from Linux ss command output
👍2
Написал заметку как сеть в Kubernetes может обманывать при учете объемов трафика. Не без помощи ebpf.
https://alebsys.github.io/posts/metallb-calico-ebpf/
#kubernetes #calico #ebpf #metallb #linux
https://alebsys.github.io/posts/metallb-calico-ebpf/
#kubernetes #calico #ebpf #metallb #linux
alebsys.github.io
Где мой трафик?
Наблюдаемость и простота отладки одни из важнейших свойств системы, которые следует учитывать уже на этапе выбора технологий. В противном случае может быть больно и дорого.
Следующий этап - разобраться как технология устроена и желательно сделать это еще…
Следующий этап - разобраться как технология устроена и желательно сделать это еще…
👍4
Let's talk about resources isolation
Ветка на форуме proxmox, где топик-стартер подсвечивает недостатки существующих инструментов изоляции ресурсов в proxmox.
В частности отсутствие функционала "из коробки":
- vCPU pinning, что прямо или косвенно приводит к излишнему context-switching и L3 cache промахам;
- SMP-aware pinning - два логических ядра не всегда равны двум физическим (hyper threading) и при планировании тредов на процессор хорошо бы учитывать chiplets - задержка доступа к кешу между соседними ядрами может различаться в разы.
Автор подсвечивает пять уровней изоляции ресурсов виртуальной машины на гипервизоре и как их можно достичь:
1. CPU pinning тредов VM;
2. Освобождение vCPU от обработки IRQ;
3. Изоляция VM от userspace процессов гипервизора;
4. Изоляция VM от kernelspace процессов гипервизора;
5. Изоляция VM от других VM на гипервизоре (cgroups).
---
Тред пригодится в борьбе за производительность CPU-bound приложений в виртуальных окружениях.
#virualization #proxmox #linux #performance #tuning
Ветка на форуме proxmox, где топик-стартер подсвечивает недостатки существующих инструментов изоляции ресурсов в proxmox.
В частности отсутствие функционала "из коробки":
- vCPU pinning, что прямо или косвенно приводит к излишнему context-switching и L3 cache промахам;
- SMP-aware pinning - два логических ядра не всегда равны двум физическим (hyper threading) и при планировании тредов на процессор хорошо бы учитывать chiplets - задержка доступа к кешу между соседними ядрами может различаться в разы.
Автор подсвечивает пять уровней изоляции ресурсов виртуальной машины на гипервизоре и как их можно достичь:
1. CPU pinning тредов VM;
2. Освобождение vCPU от обработки IRQ;
3. Изоляция VM от userspace процессов гипервизора;
4. Изоляция VM от kernelspace процессов гипервизора;
5. Изоляция VM от других VM на гипервизоре (cgroups).
---
Тред пригодится в борьбе за производительность CPU-bound приложений в виртуальных окружениях.
#virualization #proxmox #linux #performance #tuning
Proxmox Support Forum
[TUTORIAL] - Hey Proxmox & Community - Let's talk about...
This post is going to be pretty long too long to fit in a single post, but it represents a summary and lessons learned over ~3 weeks of experiments. This post is a half-tutorial and half-RFC so...
👍1👏1
Написал в блог заметку о методологии "Thread State Analysis" (TSA).
Это когда о поведении системы судят по тому, в каком состоянии (state) пребывают её потоки: running, sleep, stopped и т.д.
TSA, как и другие высокоуровневые методологии (USE, RED), может помочь сориентироваться, определить направления для дальнейшего анализа и сократить общее время устранения проблем.
tags: #methodology #linux #troubleshooting
Это когда о поведении системы судят по тому, в каком состоянии (state) пребывают её потоки: running, sleep, stopped и т.д.
TSA, как и другие высокоуровневые методологии (USE, RED), может помочь сориентироваться, определить направления для дальнейшего анализа и сократить общее время устранения проблем.
tags: #methodology #linux #troubleshooting
www.alebedev.tech
Thread State Analysis
Сессия траблшутинга - это не только конечный результат, но и процесс, протекающий с различной степенью эффективности. Одного умения пользоваться инструментами, знать флаги и уверенно работать в консоли недостаточно. Необходима систематизация.
👍1🔥1
Есть такой ресурс sadservers.com, позиционирует себя как «leetcode для linux”.
На нём собраны задачки разной степени сложности из разряда «процесс PostgreSQL перестал работать, найди причину и устрани».
Подобное может встречаться на секциях технических собесов, что добавляет полезности, да и просто интересно проверить свои навыки.
В качестве пробы пера записал видео с прохождением первой задачи с небольшими теоретическими отступлениями.
На нём собраны задачки разной степени сложности из разряда «процесс PostgreSQL перестал работать, найди причину и устрани».
Подобное может встречаться на секциях технических собесов, что добавляет полезности, да и просто интересно проверить свои навыки.
В качестве пробы пера записал видео с прохождением первой задачи с небольшими теоретическими отступлениями.
YouTube
SadServers #1 | Saint John
#sadservers #linux #devops #kubernetes #sre
Решаем первую задачу на sadservers.com - "Saint John", в которой:
- разберем как печатать содержимое файла в реальном времени;
- найдем процесс по открытому им файлу;
- посмотрим как под капотом устроена утилита…
Решаем первую задачу на sadservers.com - "Saint John", в которой:
- разберем как печатать содержимое файла в реальном времени;
- найдем процесс по открытому им файлу;
- посмотрим как под капотом устроена утилита…
👍12
TCP Congestion Control в разных окружениях
Написал заметку как влияет потеря сетевых пакетов на пропускную способность TCP соединения.
p.s. катастрофически.
tags: #linux #tcp #performance
Написал заметку как влияет потеря сетевых пакетов на пропускную способность TCP соединения.
p.s. катастрофически.
tags: #linux #tcp #performance
www.alebedev.tech
TCP Congestion Control in Action
Протестировал работу TCP Congestion Control в Linux в различных по качеству окружениях, поделюсь результатами.
👍6
SadServers №15 | Middle-level | Tokyo
Траблшутинг в ленту!
Tokyo - пятнадцатая задача среднего (middle) уровня на sadservers.com:
- изучим состояние сокетов через ss;
- посмотрим на ретрансмиты в tcpdump;
- поправив правила netfilter (iptables);
- и наконец приведем в чувства webserver.
#sadservers #linux #devops #troubleshooting #sre #tcpdump
Траблшутинг в ленту!
Tokyo - пятнадцатая задача среднего (middle) уровня на sadservers.com:
- изучим состояние сокетов через ss;
- посмотрим на ретрансмиты в tcpdump;
- поправив правила netfilter (iptables);
- и наконец приведем в чувства webserver.
#sadservers #linux #devops #troubleshooting #sre #tcpdump
YouTube
SadServers №15 | Middle-level | Tokyo
#sadservers #linux #devops #troubleshooting #sre #tcpdump
Tokyo - пятнадцатая задача среднего (middle) уровня на sadservers.com:
- изучим состояние сокетов через ss;
- посмотрим на ретрансмиты в tcpdump;
- поправив правила netfilter (iptables);
- и наконец…
Tokyo - пятнадцатая задача среднего (middle) уровня на sadservers.com:
- изучим состояние сокетов через ss;
- посмотрим на ретрансмиты в tcpdump;
- поправив правила netfilter (iptables);
- и наконец…
👍9❤1
Kafka и медленная запись
Новая заметка по расследованию деградации записи в Kafka, с флеймграфом и флагами.
#troubleshooting #performance #linux #kafka #кейс
Новая заметка по расследованию деградации записи в Kafka, с флеймграфом и флагами.
#troubleshooting #performance #linux #kafka #кейс
www.alebedev.tech
Kafka и медленная запись
Разработчики провели нагрузочные тесты и выявили значительные задержки при записи данных в Kafka, что приводило к накоплению лага.
Я подключился к анализу причин низкой производительности.
Сильно упрощенный флоу:
приложение пишет в Kafka (кластер на виртуальных…
Я подключился к анализу причин низкой производительности.
Сильно упрощенный флоу:
приложение пишет в Kafka (кластер на виртуальных…
🔥10👍4
CPU Usage не так прост в интерпретации, как может показаться.
Сложность в том, что показатель включает в себя не только работу CPU, но и время обращения к памяти.
А так как память на порядки медленнее процессора, то на ожидание ответа может уходить 90%+ времени.
Чтобы точнее интерпретировать CPU Usage стоит присмотреться к показателю IPC (Instructions Per Cycle) - сколько процессор выполняет инструкций за один такт.
В условиях современных суперскалярных процессоров этот показатель может достигать четырех и более инструкций.
Хотя в реальных нагрузках значение IPC будет существенно меньше (0.7 - 1.5).
Таким образом высокий CPU Usage при низком IPC (<1) может говорить не о недостатке вычислительных мощностей (и это первое, что приходит в голову), а о проблемах с IO - недостаток кешей и/или их плохая локальность, слишком частое обращение к памяти и подобное.
Для лучшего погружения в тему читай:
* CPU Utilization is Wrong от Brendan Gregg;
* IPC is to CPU% What Milk is to Cinnamon Toast Crunch от Mark Dawson.
——————————————
P.S. получить значение IPC можно с помощью node_exporter через perf коллектор, например так:
———————————————
P.P.S. этот же пост, но на linkedin.
tags: #cpu #theory #linux
Сложность в том, что показатель включает в себя не только работу CPU, но и время обращения к памяти.
А так как память на порядки медленнее процессора, то на ожидание ответа может уходить 90%+ времени.
Чтобы точнее интерпретировать CPU Usage стоит присмотреться к показателю IPC (Instructions Per Cycle) - сколько процессор выполняет инструкций за один такт.
В условиях современных суперскалярных процессоров этот показатель может достигать четырех и более инструкций.
Хотя в реальных нагрузках значение IPC будет существенно меньше (0.7 - 1.5).
Таким образом высокий CPU Usage при низком IPC (<1) может говорить не о недостатке вычислительных мощностей (и это первое, что приходит в голову), а о проблемах с IO - недостаток кешей и/или их плохая локальность, слишком частое обращение к памяти и подобное.
Для лучшего погружения в тему читай:
* CPU Utilization is Wrong от Brendan Gregg;
* IPC is to CPU% What Milk is to Cinnamon Toast Crunch от Mark Dawson.
——————————————
P.S. получить значение IPC можно с помощью node_exporter через perf коллектор, например так:
sum(rate(node_perf_instructions_total{instance=~"$node",job="$job"}[$__rate_interval])) / sum(rate(node_perf_cpucycles_total{instance=~"$node",job="$job"}[$__rate_interval]))
———————————————
P.P.S. этот же пост, но на linkedin.
tags: #cpu #theory #linux
Wikipedia
Instructions per cycle
measure of processing speed: the average number of instructions executed for each clock cycle
👍12🔥6✍2❤1
Мониторинг TCP: метрики Zero Window 🚀
Протокол TCP обеспечивает множество функций, включая управление перегрузками.
Для этого используется механизм скользящего окна (sliding window) — объём данных, который отправитель передаёт без подтверждения от получателя.
Размер окна динамически регулируется в зависимости от объёма свободного места в буфере получателя (
Когда буфер получателя заполняется (получатель не успевает за отправителем), TCP расценивает это как перегрузку и уменьшает размер окна в ACK-сегменте вплоть до нуля (Zero Window Advertisement).
Таким образом, при корректной настройке скорости между отправителем и получателем, переполнения очередей удаётся избежать.
С одной стороны, это позволяет избежать потерь пакетов, ретрансмитов и лишней нагрузки на сеть. С другой — мы можем не заметить, что получатель замедлился, и проблема останется скрытой.
❗️❗️❗️Интерпретация метрик ниже ошибочна, за исправленным описанием прошу сюда https://t.me/troubleperf/65 ❗️❗️❗️
К счастью
*
*
*
*
Эти метрики вместе с классическими показателями переполнения буфера и out-of-order очереди позволяют точнее оценивать состояние системы и вовремя выявлять возможные проблемы.
P.S. Лайк можно занести сюда.
tags: #tcp #linux
Протокол TCP обеспечивает множество функций, включая управление перегрузками.
Для этого используется механизм скользящего окна (sliding window) — объём данных, который отправитель передаёт без подтверждения от получателя.
Размер окна динамически регулируется в зависимости от объёма свободного места в буфере получателя (
net.ipv4.tcp_rmem
).Когда буфер получателя заполняется (получатель не успевает за отправителем), TCP расценивает это как перегрузку и уменьшает размер окна в ACK-сегменте вплоть до нуля (Zero Window Advertisement).
Таким образом, при корректной настройке скорости между отправителем и получателем, переполнения очередей удаётся избежать.
С одной стороны, это позволяет избежать потерь пакетов, ретрансмитов и лишней нагрузки на сеть. С другой — мы можем не заметить, что получатель замедлился, и проблема останется скрытой.
❗️❗️❗️Интерпретация метрик ниже ошибочна, за исправленным описанием прошу сюда https://t.me/troubleperf/65 ❗️❗️❗️
К счастью
/proc/net/netstat
позволяет отслеживать события, связанные с нулевым окном:*
TCPFromZeroWindowAdv
— сколько раз отправитель получил уведомление о нулевом окне;*
TCPToZeroWindowAdv
— сколько раз получатель установил нулевое окно;*
TCPWantZeroWindowAdv
— общее время, когда отправитель не мог отправить данные из-за нулевого окна;*
TCPZeroWindowDrop
— сколько раз отправитель отбрасывал пакеты из-за нулевого окна.Эти метрики вместе с классическими показателями переполнения буфера и out-of-order очереди позволяют точнее оценивать состояние системы и вовремя выявлять возможные проблемы.
☝️ показатели нулевого окна доступны в node_exporter через коллектор netstat
P.S. Лайк можно занести сюда.
tags: #tcp #linux
Linkedin
Мониторинг TCP: метрики Zero Window 🚀 | Aleksandr Lebedev
Мониторинг TCP: метрики Zero Window 🚀
Протокол TCP обеспечивает множество функций, включая управление перегрузками.
Для этого используется механизм скользящего окна (sliding window) — объём данных, который отправитель передаёт без подтверждения от получателя.…
Протокол TCP обеспечивает множество функций, включая управление перегрузками.
Для этого используется механизм скользящего окна (sliding window) — объём данных, который отправитель передаёт без подтверждения от получателя.…
🔥16❤3
Investigation of a Cross-regional Network Performance Issue
Траблшутинг от Netflix: исследование причин низкой скорости сети между дата-центрами.
Подобные статьи люблю за то, что можно:
1. "подсмотреть", как инженеры строят гипотезы, проверяют их и находят решения;
2. узнать практические приёмы/фишки и применить в своей работе.
Из интересного
— контейнерам в Netflix по умолчанию ограничивают пропускную способность сети (интересно на основе чего выбираются те или иные значения);
— в окружениях за NAT пары
— в ядре Linux 6.6+ изменился механизм расчёта TCP Receive Window:
— ранее использовался статический параметр
— теперь применяются динамические расчёты на основе
Кроме того, упоминается поле tcp_sock->window_clamp:
Звучит как баг, а не фича. Или это все работает немного не так;)
P.S. Подробнее вопрос Receive Window разбирается Cloudflare в Optimizing TCP for high WAN throughput while preserving low latency.
tags: #tcp #linux #kernel
Траблшутинг от Netflix: исследование причин низкой скорости сети между дата-центрами.
Подобные статьи люблю за то, что можно:
1. "подсмотреть", как инженеры строят гипотезы, проверяют их и находят решения;
2. узнать практические приёмы/фишки и применить в своей работе.
Из интересного
— контейнерам в Netflix по умолчанию ограничивают пропускную способность сети (интересно на основе чего выбираются те или иные значения);
— в окружениях за NAT пары
ip:port
на сервере и клиенте отличаются. Для идентификации одного TCP-стрима можно фильтровать пакеты по Sequence Numbers;— в ядре Linux 6.6+ изменился механизм расчёта TCP Receive Window:
— ранее использовался статический параметр
net.ipv4.tcp_adv_win_scale
.— теперь применяются динамические расчёты на основе
scaling_ratio
, стартовое значение которого — 0.25.Кроме того, упоминается поле tcp_sock->window_clamp:
Это максимальное значение окна приёма, которое может быть объявлено. Оно устанавливается как 0.25 от rcvbuf на основе начального значения scaling_ratio. Из-за этого размер окна ограничен этим значением и не может увеличиваться.
Звучит как баг, а не фича. Или это все работает немного не так;)
P.S. Подробнее вопрос Receive Window разбирается Cloudflare в Optimizing TCP for high WAN throughput while preserving low latency.
tags: #tcp #linux #kernel
Medium
Investigation of a Cross-regional Network Performance Issue
Hechao Li, Roger Cruz
🔥8
Как считается TCP Window Clamp
Ранее я упоминал статью Netflix Investigation of a Cross-regional Network Performance Issue. В ней разбирается деградация скорости TCP-соединений между дата-центрами и проблема возникла из-за изменения алгоритма расчёта TCP Receive Window в новых версиях ядра.
Как часто бывает, такие материалы оставляют больше вопросов, чем ответов — “know unknown” чистой воды.
Я покопался в исходниках Linux, чтобы лучше понять механизм подсчета TCP Window. Делюсь изысканиями:)
tags: #tcp #linux #kernel
Ранее я упоминал статью Netflix Investigation of a Cross-regional Network Performance Issue. В ней разбирается деградация скорости TCP-соединений между дата-центрами и проблема возникла из-за изменения алгоритма расчёта TCP Receive Window в новых версиях ядра.
Как часто бывает, такие материалы оставляют больше вопросов, чем ответов — “know unknown” чистой воды.
Я покопался в исходниках Linux, чтобы лучше понять механизм подсчета TCP Window. Делюсь изысканиями:)
tags: #tcp #linux #kernel
🔥3👏2
Scaling in the Linux Networking Stack (scaling.txt)
Документ от разработчиков ядра Linux описывает пять техник, которые помогают повысить производительность сетевого стека в многоядерных системах.
Это:
* RSS: Receive Side Scaling
* RPS: Receive Packet Steering
* RFS: Receive Flow Steering
* Accelerated Receive Flow Steering
* XPS: Transmit Packet Steering
В нашей инфраструктуре мы уже давно и успешно используем RSS.
Это аппаратная технология, суть следующая.
Когда поступает сетевой пакет, на основе его заголовков вычисляется хеш. Полученное значение сопоставляется с таблицей, где каждому значению соответствует определенная очередь (RX).
Каждая RX-очередь привязана к конкретному ядру процессора.
Таким образом:
1. Обработка трафика распределяется между несколькими CPU, что позволяет эффективно использовать ресурсы;
2. Все пакеты одного соединения попадают в одну очередь. Это исключает проблему "out of order" пакетов.
Однако бывают ситуации, когда распределить обработку трафика между ядрами не получается, и отдельное ядро или группа ядер оказывается сильно перегруженной:
- одно конкретное соединение прокачивает кратно больший объем трафика, чем другие;
- RX-очередей в системе меньше, чем доступных CPU.
Мы, например, сталкивались с такими проблемами при использовании MetalLB в L2-режиме: весь трафик шел через одну машину MetalLB (мастер) и "приклеивался" к одной RX-очереди на Ingress Controller. Остальные ядра и RX-очереди при этом простаивали.
В подобных случаях может помочь другая техника, описанная в том же документе — RPS (Receive Packet Steering).
RPS — это программная реализация RSS. Она позволяет распределить RX-очереди по конкретным ядрам, выравнивая нагрузку между ними.
Но есть и минусы:
- Программная реализация создает дополнительную нагрузку на CPU, что проявляется в увеличении числа IRQ на графике загрузки процессора;
- Снижается "локальность" данных в кэшах процессора, что может повлиять на производительность.
(на скрине RPS включили после 16:00)
———
Тема сложная, и я не уверен, что до конца понимаю, как это все работает;)
Было бы интересно узнать, какие техники масштабирования трафика используете вы и как справляетесь с подобными проблемами.
Дальнейшее чтение:
- сам документ scaling.txt
- расшифровка доклада от Одноклассников, где ребята решали похожие проблемы;
- примерно тоже самое, но забугорный доклад по перформансу сетевого стека.
tags: #network #tuning #linux #кейс
Документ от разработчиков ядра Linux описывает пять техник, которые помогают повысить производительность сетевого стека в многоядерных системах.
Это:
* RSS: Receive Side Scaling
* RPS: Receive Packet Steering
* RFS: Receive Flow Steering
* Accelerated Receive Flow Steering
* XPS: Transmit Packet Steering
В нашей инфраструктуре мы уже давно и успешно используем RSS.
Это аппаратная технология, суть следующая.
Когда поступает сетевой пакет, на основе его заголовков вычисляется хеш. Полученное значение сопоставляется с таблицей, где каждому значению соответствует определенная очередь (RX).
Каждая RX-очередь привязана к конкретному ядру процессора.
Таким образом:
1. Обработка трафика распределяется между несколькими CPU, что позволяет эффективно использовать ресурсы;
2. Все пакеты одного соединения попадают в одну очередь. Это исключает проблему "out of order" пакетов.
Однако бывают ситуации, когда распределить обработку трафика между ядрами не получается, и отдельное ядро или группа ядер оказывается сильно перегруженной:
- одно конкретное соединение прокачивает кратно больший объем трафика, чем другие;
- RX-очередей в системе меньше, чем доступных CPU.
Мы, например, сталкивались с такими проблемами при использовании MetalLB в L2-режиме: весь трафик шел через одну машину MetalLB (мастер) и "приклеивался" к одной RX-очереди на Ingress Controller. Остальные ядра и RX-очереди при этом простаивали.
В подобных случаях может помочь другая техника, описанная в том же документе — RPS (Receive Packet Steering).
RPS — это программная реализация RSS. Она позволяет распределить RX-очереди по конкретным ядрам, выравнивая нагрузку между ними.
Но есть и минусы:
- Программная реализация создает дополнительную нагрузку на CPU, что проявляется в увеличении числа IRQ на графике загрузки процессора;
- Снижается "локальность" данных в кэшах процессора, что может повлиять на производительность.
(на скрине RPS включили после 16:00)
———
Тема сложная, и я не уверен, что до конца понимаю, как это все работает;)
Было бы интересно узнать, какие техники масштабирования трафика используете вы и как справляетесь с подобными проблемами.
Дальнейшее чтение:
- сам документ scaling.txt
- расшифровка доклада от Одноклассников, где ребята решали похожие проблемы;
- примерно тоже самое, но забугорный доклад по перформансу сетевого стека.
tags: #network #tuning #linux #кейс
👍13
Сетевой анализ с eBPF: измеряем Round Trip Time
Под катом:
* мои рассуждения о сложности интерпретации latency в современных системах;
* небольшой гайд по eBPF - напишем по шагам инструмент, который поможет отвечать на вопрос: "причина замедления в приложении или в инфраструктуре?".
Полезного чтения!
tags: #eBPF #Linux #SRE #TCP
Длительность (latency) — ключевой показатель производительности системы. На первый взгляд всё просто: рост задержки — признак деградации. Сложность в деталях...
Под катом:
* мои рассуждения о сложности интерпретации latency в современных системах;
* небольшой гайд по eBPF - напишем по шагам инструмент, который поможет отвечать на вопрос: "причина замедления в приложении или в инфраструктуре?".
Полезного чтения!
tags: #eBPF #Linux #SRE #TCP
www.alebedev.tech
Сетевой анализ с eBPF: измеряем Round Trip Time
Разбираем сложность интерпретации Latency и пишем свой инструмент на eBPF, который эту сложность снижает.
👍19
photo_2025-01-20_08-36-01.jpg
60.5 KB
Ранее я писал о баге Haproxy: после рестарта треды не завершались, что приводило к их накоплению, память иссякала и приходил OOM Killer.
Проблему решали костылем — директива hard-stop-after принудительно завершает треды после рестарта.
Но Haproxy не сдается и наносит ответный удар!
Симптомы схожи: утечка памяти.
Но сбой наступает когда (это гипотеза) заканчивается память для TCP-буферов (
На скрине такой период отмечен красным прямоугольником.
Где
Оказалось, что система насыщается "повисшими" соединениями, чьи буферы сокетов содержат данные:
где:
*
*
А раз есть не прочитанные данные, значит таймер TCP keepalive не взводится:
Был бы повод, а костыль найдется!
Ребята из CloudFlare писали в свое время статью When TCP sockets refuse to die, где в виде решения предлагалось использовать опцию сокета
В свою очередь Haproxy поддерживает ее через tcp-ut.
Посмотрим, как себя покажет.
tags: #tcp #linux #kernel #troubleshooting #кейс
Проблему решали костылем — директива hard-stop-after принудительно завершает треды после рестарта.
Но Haproxy не сдается и наносит ответный удар!
Причины еще предстоит выяснить, поэтому это скорее "заметка с полей"
Симптомы схожи: утечка памяти.
Но сбой наступает когда (это гипотеза) заканчивается память для TCP-буферов (
net.ipv4.tcp_mem
) - ядро с переменным успехом пытается освободить память для новых / существующих соединений, что приводит к затруднению в сетевых взаимодействиях.На скрине такой период отмечен красным прямоугольником.
# sysctl net.ipv4.tcp_mem
net.ipv4.tcp_mem = 90435 120582 180870
Где
180870
- максимальное значение (в страницах памяти) под все TCP сокеты в системе, что равно ~ 706MB. Оказалось, что система насыщается "повисшими" соединениями, чьи буферы сокетов содержат данные:
# ss -ntOai | awk '{for(i=1;i<=NF;i++)if($i~/^lastsnd:/){split($i,a,":");print a[2], $2, $4, $5}}' | sort -n | tail
#lastsnd # Recv-Q #Src #Dst
234423668 157355 10.11.12.4:57354 10.11.6.123:80
235316436 302417 10.11.12.4:56232 10.11.6.124:80
238200680 301585 10.11.12.4:37940 10.11.6.124:80
238726828 300103 10.11.12.4:58944 10.11.6.124:80
243816724 297015 10.11.12.4:51700 10.11.6.125:80
251456440 302959 10.11.12.4:52324 10.11.6.125:80
252237780 302464 10.11.12.4:47786 10.11.6.123:80
257868244 163453 10.11.12.4:41568 10.11.6.125:80
259905196 300433 10.11.12.4:40202 10.11.6.123:80
261307944 214022 10.11.12.4:54888 10.11.6.123:80 # это ~ 72 часа
где:
*
lastsnd
- время с последней отправки данных, в милисекундах;*
Recv-Q
- объем не прочитанных данных, в байтах.А раз есть не прочитанные данные, значит таймер TCP keepalive не взводится:
static void tcp_keepalive_timer (struct timer_list *t)
{
...
/* It is alive without keepalive 8) */
if (tp->packets_out || !tcp_write_queue_empty(sk))
goto resched;
...
resched:
inet_csk_reset_keepalive_timer (sk, elapsed);
goto out;
...
out:
bh_unlock_sock(sk);
sock_put(sk);
}
Был бы повод, а костыль найдется!
Ребята из CloudFlare писали в свое время статью When TCP sockets refuse to die, где в виде решения предлагалось использовать опцию сокета
TCP_USER_TIMEOUT
:...it specifies the maximum amount of time in milliseconds that transmitted data may remain unacknowledged, or buffered data may remain untransmitted (due to zero window size) before TCP will forcibly close the corresponding connection and return **ETIMEDOUT** to the application...
В свою очередь Haproxy поддерживает ее через tcp-ut.
Посмотрим, как себя покажет.
tags: #tcp #linux #kernel #troubleshooting #кейс
👍21🔥2
(Не) очевидные особенности настроек TCP сокетов. Часть 1.
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
Нас интересует значение
Окей, допустим мы хотим сделать его равным 6291456 байт (~6мб).
В Nginx за размер буфер приема отвечает параметр
Вносим изменения в конфиг и перезапускаем Nginx:
Проверяем:
———
Среднее значение
Документация к
1. ядро будет удваивать переданное значение (что и увидим в`rb`)
2. дефолтное (начальное) равно
3. максимум задается через
Окей, произведем расчеты:
Похоже, что мы уперлись в
Получаем искомое
Промежуточный итог: если мы выставляем руками размеры буферов на уровне приложение (опция
Следующая часть.
tags: #tcp #linux #kernel
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb131072,t0,tb16384,f0,w0,o0,bl0,d0)
Нас интересует значение
rb
- 131072 байт. Окей, допустим мы хотим сделать его равным 6291456 байт (~6мб).
В Nginx за размер буфер приема отвечает параметр
rcvbuf
, см. док .Вносим изменения в конфиг и перезапускаем Nginx:
# grep listen /etc/nginx/nginx.conf
listen 80 rcvbuf=6291456;
# systemctl restart nginx
Проверяем:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb425984,t0,tb16384,f0,w0,o0,bl0,d0)
425984
не похоже на 6291456
;)———
# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.ipv4.tcp_rmem = 4096 131072 18874368
...
Среднее значение
tcp_rmem
соответствует размеру буфера до изменений, а новое (425984
) не совпадает ни с чем.Документация к
rcvbuf
говорит, что настройка соответствует опции сокета SO_RCVBUF
:# man 7 socket
SO_RCVBUF
Sets or gets the maximum socket receive buffer in bytes. The kernel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(2), and this doubled value is returned by getsockopt(2). The default value is set by the /proc/sys/net/core/rmem_default file, and the maximum allowed value is set by the /proc/sys/net/core/rmem_max file...
1. ядро будет удваивать переданное значение (что и увидим в`rb`)
2. дефолтное (начальное) равно
rmem_default
;3. максимум задается через
rmem_max
.Причины удвоения (хотя там могут быть разные варианты) стоит искать в "man 7 tcp" и в "net.ipv4.tcp_adv_win_scale". Или в подробной статье от CloudFlare.
Окей, произведем расчеты:
425984 / 2 = 212992
.Похоже, что мы уперлись в
net.core.rmem_max
:# sysctl net.core.rmem_max=6291456
net.core.rmem_max = 6291456
# nginx -s reload
# ss -ntlmO | grep '0.0.0.0:80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb12582912,t0,tb16384,f0,w0,o0,bl0,d0)
Получаем искомое
rb
в 12582912
(6mb * 2). Промежуточный итог: если мы выставляем руками размеры буферов на уровне приложение (опция
SO_RCVBUF
), следует учесть это и в net.core.rmem_max
.Следующая часть.
tags: #tcp #linux #kernel
The Cloudflare Blog
Optimizing TCP for high WAN throughput while preserving low latency
Tuning TCP servers for both low latency and high WAN throughput usually involves making tradeoffs. Due to the breadth of products and variety of traffic patterns at Cloudflare, we need both. In this post, we describe how we modified the Linux kernel to optimize…
🔥15
(Не) очевидные особенности настроек TCP сокетов. Часть 2.
Начало тут.
Есть мнение, что механизмы autotuning TCP в Linux не просто так придумали и в норме стоит пользоваться именно ими, а хардкод стоит избегать.
Потому разберемся с настройкой
Перефразирую:
- дефолтное значение
- максимальное значение
Делаем промежуточные вывод, что:
1.
2.
Проверим!
Начнем с конца:
Действительно, максимальный
Теперь проверим, что
Размер буфера выставляется равным дефолтному
——
Особо пытливым для перепроверки можно обратиться к исходникам:
2. либо в определении начального TCP окна:
что все таки не бьется с документацией.
Выходит обманывают нас разработчики или я так интерпретирую тексты :)
Окончательные выводы:
1.
2.
В итоге решение задачи может быть следующим:
tags: #tcp #linux #kernel
Начало тут.
Есть мнение, что механизмы autotuning TCP в Linux не просто так придумали и в норме стоит пользоваться именно ими, а хардкод стоит избегать.
Потому разберемся с настройкой
net.ipv4.tcp_rmem
и узнаем оказывает ли на него влияние net.core.rmem_max
:# man 7 tcp
...
tcp_rmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These parameters are used by TCP to regulate receive buffer sizes. ...
min minimum size of the receive buffer used by each TCP socket. The default value is the system page size. (On Linux 2.4, the default value is 4 kB, lowered to PAGE_SIZE bytes in low-memory systems.)...
default the default size of the receive buffer for a TCP socket. This value overwrites the initial default buffer size from the generic global net.core.rmem_default defined for all protocols...
max the maximum size of the receive buffer used by each TCP socket. This value does not override the global net.core.rmem_max. This is not used to limit the size of the receive buffer declared using SO_RCVBUF on a socket...
Перефразирую:
- дефолтное значение
tcp_rmem
перезаписывает net.core.rmem_default
— это мы заметили в самом начале, до использования rcvbuf
;- максимальное значение
tcp_rmem
НЕ перезаписывает net.core.rmem_max
и НЕ используется при выставлении SO_RCVBUF
.Делаем промежуточные вывод, что:
1.
net.core.rmem_max
задает жесткий лимит на размер TCP буфера;2.
tcp_rmem
не участвует в игре при выставлении SO_RCVBUF
.Проверим!
Начнем с конца:
# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 6291456
net.ipv4.tcp_rmem = 4096 131072 18874368
### Выставляем максимальное значение tcp_rmem ниже rmem_max
# sysctl net.ipv4.tcp_rmem="4096 131072 851968"
net.ipv4.tcp_rmem = 4096 131072 851968
# grep listen /etc/nginx/nginx.conf
listen 80 rcvbuf=6291456;
# systemctl restart nginx
# ss -ntlmO | grep '0.0.0.0:80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb12582912,t0,tb16384,f0,w0,o0,bl0,d0)
Действительно, максимальный
tcp_rmem
не сыграл.Теперь проверим, что
net.core.rmem_max
задает жесткий лимит над размером TCP сокетов:# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 6291456
net.ipv4.tcp_rmem = 4096 131072 851968
### Делаем net.core.rmem_max ниже чем дефолтный tcp_rmem, значение которого поднимем
# sysctl net.core.rmem_max=212992
net.core.rmem_max = 212992
# sysctl net.ipv4.tcp_rmem="4096 524288 851968"
net.ipv4.tcp_rmem = 4096 524288 851968
### Убираем директиву rcvbuf
# grep listen /etc/nginx/nginx.conf
listen 80;
# systemctl restart nginx
# ss -ntlmO | grep '0.0.0.0:80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:* skmem:(r0,rb524288,t0,tb16384,f0,w0,o0,bl0,d0)
Размер буфера выставляется равным дефолтному
tcp_rmem
(кстати без удвоений), который больше net.core.rmem_max
. ——
Особо пытливым для перепроверки можно обратиться к исходникам:
1. net.core.rmem_max
участвует либо в обработке опции SO_RCVBUF:...
case SO_RCVBUF:
...
__sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max)));
2. либо в определении начального TCP окна:
...
space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]));
space = max_t(u32, space, READ_ONCE(sysctl_rmem_max));
space = min_t(u32, space, *window_clamp);
*rcv_wscale = clamp_t(int, ilog2(space) - 15,
0, TCP_MAX_WSCALE);
что все таки не бьется с документацией.
Выходит обманывают нас разработчики или я так интерпретирую тексты :)
Окончательные выводы:
1.
net.core.rmem_max
играет только при ручном выставлении размеров сокетов (SO_RCVBUF
);2.
net.ipv4.tcp_rmem
напротив, не участвует в SO_RCVBUF
, зато позволяет использовать автоподстройку, что в большинстве случаев будет более гибким решением.В итоге решение задачи может быть следующим:
# sysctl net.ipv4.tcp_rmem="4096 1048576 12582912"
tags: #tcp #linux #kernel
Telegram
Performance matters!
(Не) очевидные особенности настроек TCP сокетов. Часть 1.
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*…
Задача: затюнить размеры сокетов у Nginx, чтобы без потерь переживать всплески трафика.
Уточним размер буфера чтения:
# ss -ntlmO | grep ':80 '
LISTEN 0 511 0.0.0.0:80 0.0.0.0:*…
👍23
Об IPC
(конспект по книге Performance Analysis and Tuning on Modern CPUs)
Я уже писал о показателе Instructions Per Cycle (IPC) (например тут и тут). Сейчас разберём детали глубже.
Instruction Per Cycle (IPC) — это среднее количество инструкций, завершённых за один такт процессора:
Определим ключевые понятия.
Инструкции делятся на executed и retired.
- Executed инструкции уже выполнены, но результат ещё не записан в память. Они могут выполняться вне порядка (out of order) и быть отменены, например, из-за miss branch prediction;
- Retired инструкции полностью завершены, то есть и выполнены и их результаты записаны (committed). Отменить их уже нельзя.
Executed напрямую не отслеживаются, а для retired есть отдельный счётчик:
Cycles (циклы) процессора бывают двух видов:
- core;
- reference.
Разница важна при динамическом изменении частоты процессора:
1. если CPU работает на штатной частоте: core = reference.
2. если CPU разогнан: core > reference.
Core Cycles отражают реальную текущую, когда Reference Cycles базовую (по паспорту) частоту процессора.
Следовательно IPC показывает единицу A) выполненной B) полезной работы в текущий момент.
Факторы, ограничивающие IPC
(перечислены в случайном порядке, список неполный):
- скорость памяти и cache misses;
- архитектура процессора: скалярность, загрузка слотов пайплайна;
- тип и сложность инструкций;
- branch misprediction (пенальти на ошибку по 10–25 ns);
- ...
Скалярность ограничивает количество инструкций, которые процессор может обработать за один такт, и задаёт теоретический максимум IPC.
На практике этот максимум недостижим: процессор может одновременно выполнять только определённые типы инструкций. Например, в 6-wide архитектуре за такт можно провести четыре операции сложения/вычитания, одну загрузку и одну запись, но не шесть загрузок одновременно.
to be continued...
#cpu #theory
(конспект по книге Performance Analysis and Tuning on Modern CPUs)
Я уже писал о показателе Instructions Per Cycle (IPC) (например тут и тут). Сейчас разберём детали глубже.
Instruction Per Cycle (IPC) — это среднее количество инструкций, завершённых за один такт процессора:
IPC = Retired Instructions / Core Cycles
Определим ключевые понятия.
Инструкции делятся на executed и retired.
- Executed инструкции уже выполнены, но результат ещё не записан в память. Они могут выполняться вне порядка (out of order) и быть отменены, например, из-за miss branch prediction;
- Retired инструкции полностью завершены, то есть и выполнены и их результаты записаны (committed). Отменить их уже нельзя.
Executed напрямую не отслеживаются, а для retired есть отдельный счётчик:
perf stat -e instructions -- ./a.exe
2173414 instructions # 0.80 insn per cycle
Cycles (циклы) процессора бывают двух видов:
- core;
- reference.
Разница важна при динамическом изменении частоты процессора:
1. если CPU работает на штатной частоте: core = reference.
2. если CPU разогнан: core > reference.
Core Cycles отражают реальную текущую, когда Reference Cycles базовую (по паспорту) частоту процессора.
perf stat -e cycles,ref-cycles -- ./a.exe
43340884632 cycles # 3.97 GHz <= Core Cycles
37028245322 ref-cycles # 3.39 GHz <= Reference Cycles
Следовательно IPC показывает единицу A) выполненной B) полезной работы в текущий момент.
IPC не зависит от изменения тактовой частоты, так как всегда рассчитывается на один цикл.
Факторы, ограничивающие IPC
(перечислены в случайном порядке, список неполный):
- скорость памяти и cache misses;
- архитектура процессора: скалярность, загрузка слотов пайплайна;
- тип и сложность инструкций;
- branch misprediction (пенальти на ошибку по 10–25 ns);
- ...
Скалярность ограничивает количество инструкций, которые процессор может обработать за один такт, и задаёт теоретический максимум IPC.
На практике этот максимум недостижим: процессор может одновременно выполнять только определённые типы инструкций. Например, в 6-wide архитектуре за такт можно провести четыре операции сложения/вычитания, одну загрузку и одну запись, но не шесть загрузок одновременно.
to be continued...
#cpu #theory
Telegram
Performance matters!
CPU Utilization is Wrong by Brendan Gregg
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается…
B. Gregg показывает почему метрика утилизации %CPU может вводить в заблуждение - она включает в себя не только время затраченное на полезную работу CPU, но и ожидание обращения к памяти.
Как решение предлагается…
👍16🔥9👎1