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

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

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

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


person Eric Z Beard    schedule 28.08.2008    source источник


Ответы (4)


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

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

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

person Mark Renouf    schedule 28.08.2008

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

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

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

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

person Hugo    schedule 28.08.2008

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

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

person Len Holgate    schedule 17.09.2008

Добрый день,

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

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

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

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

ХТН.

привет, Роб

person Rob Wells    schedule 28.08.2008