Как часто менеджерам, дизайнерам и UX-исследователям приходится разбираться в нюансах сетевого стека ядра Linux? Скорее всего, нечасто. Но если вам пришлось это сделать, у меня отличная новость: теперь не потребуется перевод с технического на дизайнерский! Меня зовут Наташа, я UX-исследователь в Selectel и уже прошла этот путь, полный админских терминов и бесконечных аналогий. В тексте делюсь кратким содержанием в комиксах.
«Очень давно, когда первые динозавры…»
Не пугайтесь, не настолько давно. Но давайте ненадолго вернемся в прошлый век, когда появились первые ЭВМ-серверы. Это были большие и шумные машины, которые производили сложные вычисления. Серверы обслуживали несколько пользовательских машин, чтобы снять с них относительно редкую вычислительную нагрузку. Так родился термин «сервер»: от английского «serve» — обслуживать. У них были конкретные задачи, под которые разработали первоначальную архитектуру ядра операционной системы.
С появлением интернета различные способы обмена информацией по сети стали набирать популярность, а принцип обработки сетевых пакетов был встроен в архитектуру ядра. Как итог — ядро Linux не всегда хорошо справляется с сетевой нагрузкой от наших интернет-стрим реалий и порой не отвечает требованиям высоконагруженных сервисов.
Как сетевой пакет попадает в приложение?
Обмен данными по сети осуществляется не просто между устройствами, а в конечном счете между конкретными приложениями. Например, вы загружаете гифку на свой сайт. Чтобы она попала из ноутбука в файловое хранилище на веб-сервере, этой гифке предстоит испытать несколько преобразований и пройти несколько уровней.
Для дальнейшего чтения пригодится знание 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 к приложению в пространстве пользователя:
Шаги 1-3 аналогичны дефолтному пути.
1. Прием пакета на сетевую карту в виде физического сигнала.
2. Опционально: преобразование сигнала в битовый формат внутри сетевой карты.
3. Доставка пакета в оперативную память. Она же ОЗУ или RAM.
4. Сигнал о получении нового пакета поступает на драйвер DPDK (вместо дефолтного драйвера сетевой карты).
5. Пакет с драйвера DPDK приходит напрямую в приложение, минуя ядро.
Важно отметить: как мы рассматривали выше, с «незнакомыми» приложениями драйвер работает через ядро.
Некоторые сетевые карты обладают дефолтными драйверами, которые умеют работать в обход ядра «из коробки», и их не нужно заменять. Однако настройка здесь тоже нужна.
Почему все так не делают
Операционная система — это некая среда, которая позволяет приложениям работать с разным железом. Вопросы совместимости берет на себя именно ОС, что избавляет разработчиков от необходимости создавать отдельные версии одного ПО для разных драйверов и оборудования.
У решения с внедрением DPDK отчасти есть подобная специфика: это индивидуальный подход к каждому приложению, что подразумевает высокую квалификацию системных администраторов. Кроме того, в дальнейшем потребуются поддержка и особое внимание при обновлении ОС.
Возвращаюсь к вопросу, зачем мне, UX-исследователю, нужно было разбираться в этом. Мы в Selectel развиваем свою ОС, и наша команда внедряет технологию обхода ядра на уровне системы — так, чтобы ускорение сетевого стека работало «из коробки» — в идеале, по нажатию галочки «ускорить». Недавно мы получили первые позитивные результаты внедрения, но это уже совсем другая история. Читайте в моей следующей статье. 🙂
20 ноября в 12:00 проведем презентацию SelectOS — серверной системы Selectel на базе Linux. Подключайтесь к вебинару, чтобы узнать, как мы смогли увеличить скорость сети в 4 раза и снизить задержки в 3 раза.