Модель потоков и масштабирования для TCP-сервера с epoll - PullRequest
7 голосов
/ 29 ноября 2011

Я прочитал документ C10K , а также много статей по расширению сокет-сервера. Все дороги указывают на следующее:

  1. Избегайте классической ошибки «поток на соединение».

  2. Предпочитают epoll, а не select.

  3. Аналогично, устаревший асинхронный механизм в unix может быть сложным в использовании.

Мой простой TCP-сервер просто прослушивает клиентские подключения через прослушивающий сокет на выделенном порту. Получив новое соединение, анализирует запрос и отправляет ответ обратно. Затем изящно закрывает розетку.

Мне кажется, я хорошо разбираюсь в том, как масштабировать это в одном потоке с помощью epoll. Всего один цикл, который вызывает epoll_wait для сокета прослушивания, а также для существующих клиентских соединений. По возвращении код будет обрабатывать создание новых клиентских подключений, а также управлять состоянием существующих подключений в зависимости от того, какой сокет только что получил сигнал. И, возможно, некоторая логика для управления тайм-аутами соединения, постепенного закрытия сокетов и эффективного распределения ресурсов для каждого соединения. Кажется достаточно простым.

Но что, если я хочу масштабировать это, чтобы использовать преимущества нескольких потоков и нескольких ядер процессора? Основная идея, которая приходит на ум, такова:

Один выделенный поток для прослушивания входящих соединений в TCP-сокете прослушивания. Затем набор из N потоков (или пула потоков) для обработки всех активных одновременных клиентских подключений. Затем придумайте какой-нибудь потокобезопасный способ, которым прослушивающий поток «отправит» новое соединение (сокет) одному из доступных рабочих потоков. (аля IOCP в Windows). Рабочий поток будет использовать цикл epoll на всех соединениях, которые он обрабатывает, чтобы сделать то же, что и однопоточный подход.

Я на правильном пути? Или существует стандартный шаблон проектирования для работы TCP-сервера с epoll в нескольких потоках ?

Предложения о том, как поток прослушивания отправит новое соединение в пул потоков?

Ответы [ 2 ]

2 голосов
/ 29 ноября 2011
  1. Во-первых, обратите внимание, что это C * 10K *.Не беспокойтесь, если вы меньше 100 (в обычной системе).Даже тогда это зависит от того, что делают ваши сокеты.
  2. Да, но имейте в виду, что epoll манипулирование требует системных вызовов, и их стоимость может быть или не быть более дорогой, чемстоимость управления несколькими fd_set самостоятельно.То же самое касается poll.При низких счетах дешевле выполнять обработку в пользовательском пространстве каждую итерацию.
  3. Асинхронный ввод-вывод очень болезнен, когда вы не ограничены несколькими сокетами, которые можно жонглировать по мере необходимости.Большинство людей справляются с использованием циклов событий, но это фрагментирует и инвертирует поток вашей программы.Обычно для этого также требуется использование больших, громоздких сред, поскольку надежный и быстрый цикл обработки событий нелегко получить.

Первый вопрос: вам это нужно?Если вы легко справляетесь с существующим трафиком, порождая потоки для обработки каждого входящего запроса, продолжайте делать это так.Код будет проще для него, и все ваши библиотеки будут играть хорошо.

Как я уже упоминал выше, жонглирование одновременных запросов может быть сложным.Если вы хотите сделать это за один цикл, вам также нужно будет обеспечить гарантию нехватки ресурсов процессора при генерации ваших ответов.

Предложенная вами модель диспетчеризации является типичным решением первого шага, если ваши ответы дороги длягенерировать.Вы можете разветвляться или использовать темы.Стоимость выбора или создания потока не должна учитываться при выборе механизма объединения: скорее, вы должны использовать такой механизм для ограничения или порядка нагрузки, размещенной в системе.

Пакетированиерозетки на нескольких петлях Эполла чрезмерны.Используйте несколько процессов, если вы так отчаянно.Обратите внимание, что возможно accept в сокете из нескольких потоков и процессов.

0 голосов
/ 29 ноября 2011

Я думаю, вы на правильном пути. Но я также думаю, что детали зависят от конкретной ситуации (пропускная способность, шаблоны запросов, индивидуальная обработка запросов и т. Д.). Я думаю, что вы должны попробовать и тщательно проверить.

...