Как свести к минимуму количество потоков, используемых в приложении tcp-сервера?

StackOverflow https://stackoverflow.com/questions/32198

Вопрос

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

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

Моей платформой является .NET, но поскольку базовая технология одинакова независимо от платформы, мне интересно увидеть ответы для любого языка.

Это было полезно?

Решение

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

Всякий раз, когда вы открываете сокет, он связывает его с селектором.Вы используете один поток для опроса этого селектора.Всякий раз, когда поступают данные, селектор указывает активный сокет, вы передаете эту операцию дочернему потоку и продолжаете опрос.

Таким образом, вам нужен только поток для каждой параллельной операции.Сокеты, которые открыты, но бездействуют, не будут связывать поток.

Другие советы

Более обоснованным подходом было бы использование портов завершения ввода-вывода.(Windows) С портами завершения ввода-вывода вы предоставляете операционной системе управлять опросом, что потенциально позволяет ей использовать очень высокий уровень оптимизации с поддержкой драйверов сетевых адаптеров.По сути, у вас есть очередь сетевых операций, которая управляется операционной системой, и вы предоставляете функцию обратного вызова, которая вызывается по завершении операции.Немного похоже на DMA (для жесткого диска), но для сети.

Несколько лет назад Лен Холгейт написал отличную серию статей о портах завершения ввода-вывода в Codeproject:http://www.codeproject.com/KB/IP/jbsocketserver2.aspx

И Я нашел статью о портах завершения ввода-вывода для .net (хотя и не читал ее) http://www.codeproject.com/KB/cs/managediocp.aspx

Я бы также сказал, что использовать порты завершения проще, чем пытаться написать масштабируемую альтернативу.Проблема в том, что они доступны только на NT (2000, XP, Vista).

Если бы вы использовали C ++ и Win32 напрямую, я бы посоветовал вам прочитать о перекрывающихся портах ввода-вывода и завершения ввода-вывода.У меня есть бесплатный C ++, IOCP, клиент-серверный фреймворк с полным исходным кодом, см. здесь для получения более подробной информации.

Поскольку вы используете .Net, вам следует рассмотреть возможность использования методов асинхронного сокета, чтобы вам не нужно было иметь поток для каждого соединения;есть несколько ссылок из этой моей публикации в блоге, которые могут стать полезными отправными точками: http://www.lenholgate.com/blog/2005/07/disappointing-net-sockets-article-in-msdn-magazine-this-month.html (некоторые из лучших ссылок находятся в комментариях к оригинальной публикации!)

Добрый день,

Я бы начал с рассмотрения метафоры, которую вы хотите использовать для своего фреймворка потоков.

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

Или пул потоков, где один и тот же поток всегда прослушивает входящие запросы, а затем передает запросы следующему доступному потоку в пуле потоков.

Возможно, вы захотите посетить Реактор раздел компонентов Ace, чтобы почерпнуть несколько идей.

ХТХ.

твое здоровье, Роб

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top