Кейс · высоконагруженное сетевое программное обеспечение
Высоконагруженный HTTP-сервер на C++
Учебно-исследовательский HTTP-сервер на C++: вместо потока на каждого клиента он распределяет тысячи соединений между несколькими рабочими потоками и с помощью системного вызова select() определяет, какие из них готовы к обмену данными. Нагрузочные испытания показали конкретные пределы — до 1024 соединений, около 220 МБ/с и ~3500 запросов в секунду.
Главный результат
Один процесс с фиксированным числом рабочих потоков стабильно обслуживает до 1024 одновременных клиентов — вместо создания отдельного потока на каждое соединение.
Почему обычный сервер не выдерживает тысячи клиентов
Поток на каждого клиента
Классическая модель заводит отдельный поток на соединение — на тысячах клиентов это расходует память и время планировщика.
Ресурсы кончаются раньше нагрузки
Сервер исчерпывает ресурсы на переключении контекстов и потреблении памяти задолго до реального предела канала.
Пределы неизвестны
Без нагрузочных испытаний непонятно, сколько клиентов и какой трафик сервер выдержит на самом деле.
Небезопасная отдача файлов
Наивная отдача статических файлов открывает доступ к посторонним файлам и падает на больших ответах.
Что нужно было сделать
Написать веб-сервер для отдачи статических файлов — страниц, оформления, изображений — который обслуживает множество клиентов небольшим фиксированным числом потоков, а не выделяет поток на каждого. И измерить его реальные пределы под нагрузкой.
Что я сделал
Построил сервер на неблокирующем вводе-выводе: вместо потока на клиента фиксированное число рабочих потоков распределяют между собой соединения и с помощью системного вызова select() опрашивают их на готовность к чтению и записи. Это экономит ресурсы компьютера на тысячах подключений.
Реализовал разбор запросов и корректные ответы, потоковую передачу больших статических файлов без полной загрузки в память и защиту от типичных атак и попыток получить доступ к посторонним файлам.
Как сервер обрабатывает соединения
Принимает соединения
Складывает входящие подключения в общий пул, не заводя поток на каждое.
Ждёт готовности
Опрашивает соединения вызовом select() и обрабатывает только те, что готовы к чтению или записи.
Отдаёт данные
Разбирает запрос и потоково передаёт статический файл, не загружая его целиком в память.
Освобождает
Закрывает соединение и возвращает рабочий поток в пул для следующего клиента.
Что умеет сервер
Мультиплексирование соединений
Опрашивает соединения одним вызовом select() и обслуживает множество клиентов небольшим фиксированным числом потоков.
Потоковая отдача файлов
Передаёт большие статические файлы порциями, без полной загрузки в память.
Основные возможности HTTP
Разбор запросов, корректные ответы и отдача статических файлов: страниц, стилей, изображений.
Защита от атак
Отражает типичные атаки и попытки доступа к посторонним файлам.
Нагрузочное тестирование
Серия испытаний с графиками и сравнением разных подходов к обработке соединений.
Экономия ресурсов
Никакого потока на клиента — минимум переключений контекста и памяти под нагрузкой.
Пределы определены экспериментально
Сервер прошёл серию нагрузочных испытаний, которые показали конкретные пределы: он стабильно держит до 1024 одновременных подключений — этот предел задан ограничением системного вызова select() на число отслеживаемых дескрипторов, — обеспечивает скорость передачи около 220 МБ/с и справляется примерно с 3500 запросами в секунду до начала снижения качества обслуживания.
Все результаты собраны в отчёте с графиками и сравнением разных подходов к обработке соединений — видно, за счёт чего именно выигрывает выбранная модель.

Как это выглядит
Что изменилось
Было
- —Поток на каждого клиента перегружает память и планировщик
- —Ресурсы кончаются задолго до предела канала
- —Реальные пределы сервера — неизвестны
Стало
- ✓Тысячи клиентов на фиксированном числе потоков
- ✓Большие файлы отдаются потоково, без загрузки в память
- ✓Пределы измерены: 1024 соединения, ~220 МБ/с, ~3500 запросов/с
Сервер показал, что модель с мультиплексированием соединений через select() и неблокирующим вводом-выводом обслуживает тысячи клиентов ограниченным числом потоков — с измеренными пределами и защитой отдачи файлов.