Модель серверной обработки веб-сокетов

Чтобы реализовать сервер, поддерживающий клиентов с помощью веб-сокетов, серверы поддерживают открытое HTTP-соединение с каждым клиентом? Как этот масштаб?

Что такое "модели программирования" при реализации этого типа сервера? Т.е.: большинство веб-приложений имеют сервлеты и т.д., Которые поддерживают модель типа connect- > request- > response- > close. В то время как с сетевыми сокетами соединение остается открытым неограниченное время.

Ответ 1

Обычно вам нужно работать в asynchronous, чтобы эти долгоживущие подключения работали. Существует несколько различных методов для асинхронного ввода-вывода; все из которых имеют свои преимущества и недостатки.

Тот, который уже должен быть знаком любому, кто работал с JavaScript и AJAX, является моделью обратного вызова; в котором вы отправляете запрос, и устанавливаете обратный вызов для вызова, когда он завершается. Вот как работает XMLHTTPRequest, не блокируя все остальные страницы, пока они ждут завершения одного запроса страницы. Это также работает в рамках Twisted Python, хотя он может вызывать методы для объектов или функции обратного вызова в зависимости от используемых вами интерфейсов.

Еще одна мощная модель - стиль Erlang, называемый моделью Actor, имеет множество легких процессов (например, потоков, но с нет общего состояния), каждый из которых взаимодействует друг с другом через асинхронные сообщения. Время выполнения Erlang реализовано для того, чтобы сделать тысячи процессов очень эффективным; то вы можете просто иметь один процесс для каждого подключения и отправлять сообщения другим процессам, реализующим бэкэнд приложения. Процессы Erlang также могут автоматически планироваться на нескольких потоках ОС, чтобы в полной мере использовать многоядерные системы. ejabberd, популярный Jabber-сервер (протокол чата, который требует много долгоживущих открытых подключений), реализован в Erlang, также как и Система чата Facebook.

Новый Go language от Google использует подобный подход, ближе к Hoare, сообщающему последовательно, чем модель Actl Erlang, но которая имеет много общего.

В Mac OS X 10.6 Apple представила Grand Central Dispatch вместе с блоками (по сути, закрытие) в C, С++ и Objective-C, Это позволяет что-то вроде модели обратного вызова, зависящей от AJAX или Twisted style, но с явно управляемыми очередями, которые выполняются последовательно для управления доступом к общим ресурсам в многопоточной многоядерной среде. Twisted и JavaScript работают как однопоточные, поэтому могут использовать только одно ядро, если только вы не используете несколько процессов операционной системы, которые могут быть довольно тяжелыми и увеличивать затраты на связь между ними.

Тогда существуют более традиционные модели, такие как Unix select или более современные и способные epoll или kqueue(). В них у вас обычно есть основной цикл в вашей программе, который настраивает кучу событий для просмотра (сетевой ввод-вывод возвращает еще несколько данных, файлы ввода-вывода возвращают больше данных, новое сетевое соединение и т.д.), а затем вызывает системный вызов, который блокируется до тех пор, пока не произойдет одно из этих событий, после чего вы проверите, какой из них произошел, а затем обработайте его соответствующим образом. Эти системные вызовы обычно используются для обеспечения вышеописанных структур, описанных выше.

Для очень хорошего обзора ошеломляющего массива доступных опций (с упором на более традиционные и более низкие уровни, подходы Unix), см. Проблема C10K, обзор различных методов, помогающих одновременно обрабатывать 10 000 одновременных соединений. У этого также есть хороший список библиотек C и С++ для абстрагирования по доступным различным API-интерфейсам, таким как libevent.

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

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

Ответ 2

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

Ответ 3

он отличается от http тем, что каждый последующий запрос/ответ не нужно обертывать в http-сообщение с заголовками http. поэтому приложениям реального времени не нужны накладные расходы на разбор заголовков. после начального http-подобного рукопожатия, он в основном ведет себя как обычный сотовый tcp-сокет.

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