Я прочитал документ C10K , а также много статей по расширению сокет-сервера. Все дороги указывают на следующее:
Избегайте классической ошибки «поток на соединение».
Предпочитают epoll, а не select.
Аналогично, устаревший асинхронный механизм в unix может быть сложным в использовании.
Мой простой TCP-сервер просто прослушивает клиентские подключения через прослушивающий сокет на выделенном порту. Получив новое соединение, анализирует запрос и отправляет ответ обратно. Затем изящно закрывает розетку.
Мне кажется, я хорошо разбираюсь в том, как масштабировать это в одном потоке с помощью epoll. Всего один цикл, который вызывает epoll_wait для сокета прослушивания, а также для существующих клиентских соединений. По возвращении код будет обрабатывать создание новых клиентских подключений, а также управлять состоянием существующих подключений в зависимости от того, какой сокет только что получил сигнал. И, возможно, некоторая логика для управления тайм-аутами соединения, постепенного закрытия сокетов и эффективного распределения ресурсов для каждого соединения. Кажется достаточно простым.
Но что, если я хочу масштабировать это, чтобы использовать преимущества нескольких потоков и нескольких ядер процессора? Основная идея, которая приходит на ум, такова:
Один выделенный поток для прослушивания входящих соединений в TCP-сокете прослушивания. Затем набор из N потоков (или пула потоков) для обработки всех активных одновременных клиентских подключений. Затем придумайте какой-нибудь потокобезопасный способ, которым прослушивающий поток «отправит» новое соединение (сокет) одному из доступных рабочих потоков. (аля IOCP в Windows). Рабочий поток будет использовать цикл epoll на всех соединениях, которые он обрабатывает, чтобы сделать то же, что и однопоточный подход.
Я на правильном пути? Или существует стандартный шаблон проектирования для работы TCP-сервера с epoll в нескольких потоках ?
Предложения о том, как поток прослушивания отправит новое соединение в пул потоков?