Как часто менеджерам, дизайнерам и UX-исследователям приходится вникать в проблемы сетевого стека Linux-ядра? Подозреваю, что не часто. Но если вам пришлось это сделать, у меня хорошая новость! Я уже прошла этот путь, полный админских терминов и бесконечных аналогий, и подготовила краткое содержание в комиксах. Теперь вам не нужно будет переводить с технического на дизайнерский!
Меня зовут Наташа, я UX-исследователь в Selectel. В тексте расскажу о DPDK: что это и какую проблему решает, а также зачем потребовалось юиксеру. 🙂
Используйте навигацию, если не хотите читать текст полностью:
→ «Очень давно, когда первые динозавры...»
→ Как сетевой пакет попадает в приложение?
→ А если исключить ядро из этой цепочки?
→ Почему все так не делают
«Очень давно, когда первые динозавры...»
Не пугайтесь, не настолько давно. Но давайте ненадолго вернемся в прошлый век, когда появились первые ЭВМ-серверы. Это были большие и шумные машины, которые производили сложные вычисления. Серверы обслуживали несколько пользовательских машин, чтобы снять с них относительно редкую вычислительную нагрузку. Так родился термин «сервер»: от английского «serve» — обслуживать. У них были конкретные задачи, под которые разработали первоначальную архитектуру ядра операционной системы.
С появлением интернета различные способы обмена информацией по сети стали набирать популярность, а принцип обработки сетевых пакетов был встроен в архитектуру ядра. Как итог — ядро Linux не всегда хорошо справляется с сетевой нагрузкой от наших интернет-стрим реалий и порой не отвечает требованиям высоконагруженных сервисов.
Как сетевой пакет попадает в приложение?
Обмен данными по сети осуществляется не просто между устройствами, а в конечном счете между конкретными приложениями. Например, вы загружаете гифку на свой сайт. Чтобы она попала из ноутбука в файловое хранилище на веб-сервере, этой гифке предстоит испытать несколько преобразований и пройти несколько уровней.
Для дальнейшего чтения пригодится знание OSI — эталонной семиуровневой модели передачи данных. Подробнее о том, как она устроена, — в обзоре. Если кратко, у меня есть зарисовка на эту тему.
Уровни модели OSI.
Будем считать, что гифка, которая завернута в сетевой пакет, уже улетела с вашего ноутбука в бездну сетей. Она прошла часть пути и хочет попасть на веб-сервер Nginх, который развернут на машине с Unix-подобной ОС. На подходе к серверу сетевой пакет передается в виде физического сигнала — радиоволн, фотонов или электричества, в зависимости от канала.
Рассмотрим ключевые процессы внутри сервера.
- Сетевая карта принимает сигнал, при необходимости преобразует его в набор ноликов и единичек.
- Полученный пакет переходит в оперативную память сервера (RAM, или ОЗУ).
- Ядро ОС узнает об этом через системный вызов и решает, что делать с данными.
- Из пакета извлекаются передаваемые данные, в нашем случае — гифка.
- Целевое приложение, в нашем примере — Nginх, забирает данные в свое пространство.
Теперь расскажу подробнее о пути пакета и манипуляциях, которые происходят с ним в пространстве сетевого оборудования.
1. Прием пакета на сетевую карту в виде физического сигнала.
2. Опционально: преобразование сигнала в битовый формат внутри сетевой карты.
3. Доставка пакета в оперативную память (ОЗУ, RAM).
4. Драйвер сетевой карты перемещает пакет в ОЗУ и ждет сигнал о завершении процесса и готовности пакета к обработке.
В тексте не будем подробно разбирать DMA — способ минимизировать участие центрального процессора в передаче данных. Для соответствия реальным процессам я обозначила технологию на схеме, но ее глубокое понимание для дальнейшего чтения не требуется.
Дефолтный путь сетевого пакета. Сетевое оборудование.
Как только сигнал о готовности пакета поступает на драйвер сетевой карты, он оповещает об этом ядро ОС. Если вы знакомы с системными вызовами, прерываниями и переключениями контекста, то речь именно о них. Мы переносимся в пространство ядра — и здесь узкое горлышко всего процесса.
5. Ядро вынуждено отвлечься от других задач, получив системный вызов с драйвера сетевой карты. Происходит прерывание некоторых процессов.
6. Операционная система должна посмотреть на пакет и решить, что с ним сделать. Эта информация есть в правилах, описанных админом системы. Для нашего сценария примем, что пакет хороший, и предназначен для веб-сервера Nginx.
7. В пространстве ядра происходит обработка пакета и направление полезных данных из пакета непосредственно в приложение.
8. Данные прилетели в пространство приложения, но в нашем сценарии ненадолго. Приложение забирает данные от операционной системы, обрабатывает их и, скорее всего, хочет дать обратный ответ — конечно же, тоже через ядро. И снова системный вызов и прерывание.
Дефолтный путь сетевого пакета. Пространство ядра.
Пока мы рассматриваем пример с одним пакетом, на серверы Хабра, вероятно, прилетел уже не один миллион подобных. А сколько это системных вызовов и прерываний? Ядро — как регулировщик на перегруженной дороге. Только и успевает распределять эти потоки.
Конечно, технологии не стоят на месте и некоторые процессы оптимизированы. Например, режим опроса, когда ядро не реагирует на «каждый чих», а раз в заданный период прерывается самостоятельно и проверяет наличие пакетов. Однако для высоконагруженных сервисов этого тоже может быть недостаточно.
А если исключить ядро из этой цепочки?
Дефолтный путь сетевого пакета. Полная схема.
Если исключить системные вызовы из этой цепочки, получится решение, которое называют обходом ядра (kernel bypass). Чтобы реализовать этот подход, компания Intel® разработала набор драйверов и библиотек — Data Plane Development Kit (DPDK).
Дефолтный драйвер сетевой карты «выключается», и вместо него ставится драйвер DPDK. Его особенность в том, что он «знает» о некоторых приложениях и может общаться с ними напрямую. Речь о тех приложениях, которые тоже модифицированы различными библиотеками, чтобы взаимодействовать с драйвером сетевой карты DPDK.
Таким образом, сетевой пакет проходит прямой путь от драйвера DPDK к приложению в пространстве пользователя:
Путь сетевого пакета в обход ядра.
2. Опционально: преобразование сигнала в битовый формат внутри сетевой карты.
3. Доставка пакета в оперативную память. Она же ОЗУ или RAM.
4. Сигнал о получении нового пакета поступает на драйвер DPDK (вместо дефолтного драйвера сетевой карты).
5. Пакет с драйвера DPDK приходит напрямую в приложение, минуя ядро.
Важно отметить: как мы рассматривали выше, с «незнакомыми» приложениями драйвер работает через ядро.
Некоторые сетевые карты обладают дефолтными драйверами, которые умеют работать в обход ядра «из коробки», и их не нужно заменять. Однако настройка здесь тоже нужна.
Почему все так не делают
Операционная система — это некая среда, которая позволяет приложениям работать с разным железом. Вопросы совместимости берет на себя именно ОС, что избавляет разработчиков от необходимости создавать отдельные версии одного ПО для разных драйверов и оборудования.
У решения с внедрением DPDK отчасти есть подобная специфика: это индивидуальный подход к каждому приложению, что подразумевает высокую квалификацию системных администраторов. Кроме того, в дальнейшем потребуются поддержка и особое внимание при обновлении ОС.
Возвращаюсь к вопросу, зачем мне, UX-исследователю, нужно было разбираться в этом. Мы в Selectel развиваем свою ОС, и наша команда внедряет технологию обхода ядра на уровне системы — так, чтобы ускорение сетевого стека работало «из коробки» — в идеале, по нажатию галочки «ускорить». Недавно мы получили первые позитивные результаты внедрения, но это уже совсем другая история. Читайте в моей следующей статье. :)
20 ноября в 12:00 проведем презентацию SelectOS — серверной системы Selectel на базе Linux. Подключайтесь к вебинару, чтобы узнать, как мы смогли увеличить скорость сети в 4 раза и снизить задержки в 3 раза.
А какое приложение ускорили бы вы? Делитесь своими вариантами в комментариях!
Автор: Liisign