Наверх ▲

WebSockets

Евгений Лисицкий Евгений Лисицкий Ведущий разработчик компании "Спорт Сегодня".
View more presentations from rit2010.

Евгений Лисицкий: Здравствуйте, меня зовут Евгений Лисицкий, я собираюсь рассказать о технологии WebSocket. Именно в последние полгода эта тема вызвала небывалый интерес у разработчиков, причем у разработчиков таких близких и дорогих русскому сердцу продуктов, как Apache, MochWeb, EventMachine, Twisted и многие другие.

Структура моего доклада будет такой.

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

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

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

Наконец, пятый пункт. Попробуем исследовать примеры реализации технологии будущего уже сегодня. Подумаем, как мы можем сегодня использовать WebSocket.

Итак. Интерактивный веб образно можно представить так. У нас имеется сервер, у нас имеется клиент, и у нас имеется некая среда передачи — транспорт. С сервером, на самом деле, все просто.

Как правило, сервер находится полностью в нашем распоряжении. Это значит, что мы можем туда вставить все, что нам заблагорассудится, и настраивать это так, как нам нравится. Здесь я привел некоторые технологии, которые помогают нам построить событийно-ориентированную модель (англ. Event Driven Architecture).

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

С клиентом дела обстоят чуть сложнее. Мы не можем ставить в браузерах клиента любые плагины, какие нам захочется. Тем не менее, у него есть JavaScript — шикарный язык, событийный, асинхронный, классный. Он хорош настолько, что его можно даже использовать на сервере, и тот самый NodeJS, который был на предыдущем слайде, реализован именно на нем.

Итак, что у нас есть? Отличный событийный сервер, отличный событийный клиент. В чем проблема? Проблема как раз в транспорте. Именно это самое слабое звено всего интерактивного веба.

Тут написано "HTTP", но не надо думать, что проблема именно в HTTP-протоколе. Нет, ничуть. HTTP — это шикарный, отличный, хорошо продуманный протокол. Его создавали гениальные люди, и в него с запасом заложены идеи на многие годы вперед.

Проблема возникает тогда, когда мы пытаемся заставить его играть не на своем поле. На что ориентирован HTTP? На то, чтобы передавать с сервера на клиент некие страницы и объекты значительного размера. Когда мы заставляем его работать интерактивно, он ведет себя не так хорошо, как бы нам хотелось.

Что я понимаю под "интерактивностью"?

  1. Минимальную латентность. Это значит, что человек должен получать реакцию на свое действие как можно быстрее. Принцип «нажми на кнопку — получишь результат». В идеале - молниеносно.
  2. Асинхронность, которая очень важна. Это значит, что текущая деятельность клиента не должна мешать реакции на поступающее новое событие. Если это условие не выполняется, то интерактивность теряется.

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

Но как раз в этом случае у нас начинаются проблемы, т.к. HTTP для этого не предназначен. Первое и самое главное — по своей сути протокол — асинхронный, и никакой AJAX нас не спасет.

Образно диаграмму работы можно представить следующим образом. Слева располагается классический опрос (англ. polling). Клиент запросил — сервер ответил. Клиент запрашивает: «Дай мне последние новости за 5 минут». Сервер ему присылает список новостей либо говорит: «Извини, новостей нет, приходи потом».

Конечно, тут можно ввести ряд улучшений. Посередине изображен длинный опрос (англ. long polling). Это ситуация, когда сервер, вместо того, чтобы отвечать сразу: «Новостей нет, приходи потом», задерживается с ответом до наступления какого-либо события.

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

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

Наконец, третья, весьма серьезная проблема.

Она связана с низкой эффективность HTTP в этом режиме. Дело в том, что при передаче сообщений по HTTP, они предваряются заголовками, метаданными. Кодировка, формат данных, данные и прочее. Размер заголовков варьируется от нескольких сотен байт до нескольких килобайт. Это не является проблемой, когда мы говорим о передаче, странички размером 100 килобайт или картинки размером 50 килобайт.

Но временами мы работаем в интерактивном режиме и нам нужно передавать очень маленькие сообщения, вплоть до пары-тройки десятков байт. Если мы прикрепим к нему заголовок в несколько килобайт, какова будет полезная нагрузка?

Наши иностранные коллеги смоделировали трединговое приложение. При трединге очень важно, чтобы оператор получал самые актуальные цены. Они подсчитали, что для ежесекундного обновления цены требуется присылать человеку примерно 20 байт.

Если мы эти 20 байт будем предварять примерно килобайтом заголовков... Конечно, заголовки могут варьироваться. Там могут быть куки, авторизации. Они могут отличаться как в большую, так и в меньшую сторону. В итоге мы получим довольно интересную картину эффективности.

Я обозначил достаточно широкий диапазон, т.к. многое зависит от конкретных ситуаций. Все мы знаем одно устройство, которое работает приблизительно с таким же КПД. Что же делать?

Возможно, раньше все было плохо. Но теперь у нас есть WebSocket, который решает данные проблемы.

Что такое WebSocket? Это самое радикальное расширение протокола HTTP с самого момента его появления. Очень часто WebSocket путают с тем же самым веб-сервисом или вариантом, когда поверх HTTP пристраивается некий транспорт.

WebSocket — это изменение самого HTTP на уровне парадигмы.

Что мы имели раньше? HTTP сессионный: подключился — поработал — отключился. Нужно в следующий раз — подключись снова. Синхронный: запрос — ответ. С четко разделенными ролями: клиент — сервер — протокол.

Вместо этого WebSocket представляет собой, во-первых, постоянное TCP-соединение. Он не имеет выделенных ролей. Вместо сервера и клиента у нас 2 равноправных участника обмена данными, которые обмениваются ими в полностью асинхронном режиме.

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

Когда поступит ответ? Когда угодно. Он может даже вообще не прийти, т.к. у нас теперь событийная модель работы. Вот когда возникнет событие на другом конце, тогда он и пришлет событие в соответствии со своей логикой.

Изменилось все. Самый главный вопрос — что нам это дало?

Во-первых, WebSocket входит в HTML5, он будет принят как стандарт W3C Consortium с организацией и стандартизацией веб. Это очень хорошо с той точки зрения, что инфраструктура веб будет лучше его поддерживать, значит, он будет работать более стабильно, более эффективно и более качественно, чем сегодняшние решения.

Второй важный момент. Полная двунаправленная передача данных (англ. full-duplex). Как это понять?

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

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

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

Еще одно очень важное преимущество — это низкие требования к сетевым ресурсам и максимальный КПД передачи данных. Когда мы говорили про AJAX и Comet, мы пришли к выводу, что большой заголовок — такая большая-большая гиря на ноге Меркурия, которая мешает ему быстро бежать и передавать сообщения.

Есть ли служебная информация (англ. overhead) у WebSocket? Да, она добавляет ровно 2 байта на 1 сообщение. Один байт в начале, второй байт в конце. Никаких лишних данных.

Рассмотрим вопрос о времени жизни канала в неактивном состоянии. HTTP, являясь сессионным протоколом, может декларировать нам, если не изменяет память, примерно 75 секунд жизни неактивного соединения, после чего он должен закрываться.

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

Конечно, решение этой проблемы существует. Если в течение какого-то времени событий не происходит, то отправляются пустые пакеты (пинги). Но учтем, что пакет не просто пустой, даже если он на самом деле ничего не содержит. Он содержит, как минимум, заголовок. Это характерно для всех вариаций опроса — хоть длинного, хоть короткого.

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

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

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

Еще один камень в ботинке разработчика Comet - это кроссдоменное приложение. Сегодня различные библиотеки уже содержат специальные подходы, чтобы Comet мог работать с разными доменами, а не только с тех, откуда он был загружен. Это ограничение определено в самом HTTP.

WebSocket не имеет этого ограничения в принципе. Если раньше принцип XML HTTP request и его безопасности позволял работать только со своим доменом, то на этот раз все управление безопасности было перенесено на сервер. Сервер стал решать, с запросами каких доменов он хочет работать, а с каких нет. Для этого было сделано кроссдоменное приложение, которое оказалось ничуть не сложнее, чем приложение со своим доменом.

Второй доменный вопрос — HTTP лимитирует количество соединений, одновременно работающих с одним доменом. В старых редакциях было 2 соединения, в новых — по-моему, до четырех.

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

Значит, мы можем увидеть проблемы с загрузкой других объектов с этого же домена — каких-нибудь скриптов, картинок и всего прочего.

И, наконец, последнее преимущество. На сегодня существует масса библиотек Коен. В них можно найти то, что лучше работает, протестировать и т.д. Иногда выясняется: что работает лучше, не всегда будет работать лучше в комплексе, потому что у вас уже подключена другая JavaScript-библиотека.

Взамен всему этому WebSocket предлагает очень простое и красивое API.

Это все, что нам нужно знать про API WebSocket, чтобы начать с ним работать. Всего 5 строк.

Мы плавно перешли к технической части. Как только наша страница решила, что ей нужно открыть WebSocket на определенный домен, мы создаем новый JavaScript-объект, который так и называется — WebSocket. В качестве параметра при его инициализации передаем ему URL.

Обратите внимание, используется протокол ws — сокращение очевидно. Сразу отмечу, что существует еще один протокол — wss. Это, соответственно, Secure WebSocket. То есть примерно то же самое, как http/https. Тот же WebSocket, только через SSL.

После того как объект создан, вы на него "навешиваете" 3 разновидности фукции обратного вызова). Первый — onopen — вызывается, когда ваше соединение создано и готово к работе. Здесь мы не будем делать ничего сложного. Просто известим пользователя об этом. Onclose — соответственно, наоборот, — когда ваше соединение закрыто. Наконец, onmessage вызывается каждый раз, когда вы получаете асинхронное сообщение от сервера.

В качестве параметра он принимает событие (англ. event). В event.data будет именно текстовая строка, которую вы получили.

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

Что в это время происходит в сети? Как устанавливается WebSocket соединение? Поначалу все очень похоже на HTTP.

Клиент устанавливает TCP-соединение к серверу на 80 порт, т.е. используются те же самые порты, что и в HTTP. Соответственно, WebSocket Secure вариант использует 443 порт.

Разница только в том, что GET-запрос немного необычный. Он содержит предложение произвести апгрейд соединения с WebSocket.

Еще один новый для нас заголовок - это Origin, где указывается, какая именно страница хочет открыть подключение к WebSocket. На основе него сервер и будет принимать решение, хочу ли я работать с этим доменом, разрешено или нет.

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

HTTP/1.1 код 101-ый, опять же Upgrade: WebSocket, Connection: Upgrade и снова участвует Origin. Отмечу, что Origin должен быть тот же самый, что был получен сервером. В случае получения неправильного Origin браузер должен закрывать соединение.

Как только браузер получает все необходимое, он оставляет соединение открытым и теперь оно работает, пока "жива" страница или пока соединение не будет закрыто через ws.close.

Что мы делаем, когда требуется передать сообщение? Мы передаем так называемый текстовый фрейм данных (англ. Data Frame). Это строка текста, снабженная двумя маркерами: маркером начала (нулевой байт) и маркером конца (байт FF). Это та самая двухбайтная служебная информация (overhead).

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

Что еще мне нравится? То, что в качестве единственно допустимой кодировки для передачи сообщений разработчики выбрали UTF-8. Я уже даже начинаю надеяться, что через некоторое время мы избавимся от одного из "костылей" веба и самых кодировок.

Следующий вопрос: можно ли передать с помощью WebSocket картинку или какой-нибудь другой бинарный объект? Можно. Для этого существует специальный бинарный фрейм данных. Он имеет другой признак. Вначале 0×80, далее идет длина объекта — один или несколько байт — и потом идут собственно байты. Поскольку длину мы уже указали, то нам маркер завершения, в принципе, не нужен.

К примеру, так будут начинаться некоторые объекты. Самое главное — картинка веб-дизайна — прозрачный однопиксельный GIF размером в 43 байта. Очевидно, что 2B. Кто знаком с двоичной математикой, быстро переведет в 43.

Если у нас объект чуть больше, скажем, 160 байт, то ему потребуется 2 байта длины. Дальше снова идут данные.

Здесь возникает вопрос: что значит несколько байт? Как это понять? В конце концов, мы занимаемся информационными технологиями, и у нас все должно быть строго и четко, а тут говорят "несколько байт". Здесь разработчики решили поступить очень хитро. Они не стали говорить, что 640 килобайт хватит на все, а придумали свою, очень компактную систему записи длины, которая при этом не имеет верхнего предела.

Каждый байт в этом указании длины интерпретируется по частям. Самый старший бит указывает, есть ли за ним следующий (единичка), либо что этот байт — последний в цепочке (нолик). Обрабатывается очень просто. Мы выкидываем все старшие байты, соединяем все биты и видим результат. В данном случае у нас получилось как раз 128+32=160.

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

Как я уже говорил, на сегодняшний день для многих популярных событийно-ориентированных архитектур — тех же самых EventMachine, Twisted, Tornado, MochWeb, Misultin и так далее — уже есть готовые реализации. Вы можете их просто брать и использовать.

Что нас ждет дальше? Дальше я сделал небольшой, но "осязаемый" пример применения WebSocket.

Эти два адреса — абсолютно одно и то же. Что вам удобнее, то и можете набирать. Должен оговориться заранее: это немножко авантюрный пример. Я одну технологию будущего (WebSocket) демонстрирую с помощью другой технологии будущего (Erlang).

Я действительно считаю Erlang технологией будущего для веба. Не смотрите, что он уже три с лишним десятка лет рулит в Телекомах и так далее. Для веба все-таки новичок и, на мой взгляд, он займет очень серьезную нишу именно в разработке событийных архитектур. 

Загрузилось. Сразу говорю: это просто демо-пример. Я намеренно написал его максимально просто и даже примитивно, чтобы продемонстрировать идею и не отвлекать вас на различные детали. Тут весьма спартанский дизайн. Демон написан максимально просто. Там нет каких-то фильтраций данных, нет контроля утечки памяти, конкурентности и так далее.

Как это все работает? Изначально производится авторизация. Авторизация на серверной стороне. Сервер принимает любой логин-пароль. Присылайте что хотите, там даже нет проверки на уникальность. Это сделано для того, чтобы не заставлять вас подбирать различные логины-пароли.

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

После того, как сервер подтвердил нашу авторизацию, у нас должно открыться окно сообщений, где мы можем писать. Вся работа и все общение идет исключительно через WebSocket. Мы авторизовались, мы дали запрос (новое сообщение), он ушел через WebSocket, кодированный JSON-форматом, обратно нам точно так же в JSON-формате приходит ответ. Да, друзья, я не могу писать в систему, которая не экранирует угловые скобки. Извините, XSS не прошел. Это мое внутреннее ограничение.

Замечу еще одну интересную особенность такой авторизации. Она многократно снижает нагрузку на подсистему аутентификации пользователей. Почему? Потому что, по сути, она работает только один раз — в момент установления постоянного TCP-соединения. После этого все, что идет по этому TCP-соединению, уже авторизовано и принадлежит какому-то понятному конкретному пользователю.

Отсюда же вытекает второе интересное преимущество. Теперь, чтобы выгнать неугодного пользователя из чата, нам достаточно выполнить "drop" для его WebSocket на сервере. При этом он автоматически уйдет. Это уже отдельный вопрос. То есть мы же можем его уже не авторизовать во второй раз.

Тут, в принципе, я не стал этот вариант реализовывать, но он напрашивается. Например, если вы нажмете кнопку F5, иногда можно успеть увидеть запись "WebSocket disconnected". Это тот самый обратный вызов, который у меня "навешен" на событии "disconnect".

Я так всем этим делом вдохновился, что просто не смог не процитировать Джо Армстронга, создателя языка Erlang.

Перевод, в принципе, понятен. Джо видит будущее именно за WebSocket. Comet, применяющийся ныне, еще какое-то время поживет - видимо, он пока будет использоваться. Но стратегически уже имеет смысл ориентироваться именно на WebSocket.

Я сделал небольшой сайт, который так и называется — websockets.ru. Туда я планирую выложить свою статью и все мои дальнейшие изыскания. Если эта тема вас заинтересовала, приглашаю вас присоединиться. Присылайте материалы, будем совместно разрабатывать эту тему.

Стало модно вести twitter. Должен заметить, что «чирикаю» я в нем нечасто, так что можете читать его или нет — полностью на ваше усмотрение.

Большое спасибо за внимание! Буду рад ответить на все ваши вопросы. Спасибо!

Вопросы и ответы

Вопрос:
— У меня вопрос, собственно, про авторизацию, а конкретно — про то, что происходит с cookie-настройками. Первый вопрос: что происходит с cookie, когда мы заходим на сайт chat.websockets.ru, до этого получив cookie от HTTP-сервера на chat.websockets.ru?
Потом: что будет, если мы получаем cookie от chat.websockets.ru, заходим на другой домен, и с него отправляемся на ws.websockets.ru? Что происходит с cookie? То есть когда и где какая cookie-настройка куда уйдет?
Евгений Лисицкий:
— Спасибо.
Вопрос:
— Второй вопрос сразу. Зачем нужен Origin, когда есть HTTP-referer?
Евгений Лисицкий:
— Спасибо. По cookie. Cookie в протоколе поддерживаются и передаются. Передаются cookie целевого домена. Если, например, если у нас есть cookie на домен .websockets.ru, то cookie-настройка имеет отношение к целевому серверу и будет передана на сервер. По нему мы можем сразу авторизоваться.
Как быть, когда, например, есть другой домен, которому данная cookie-настройка не подходит? Есть такой вариант. Мы можем брать текущую cookie-настройку с нашей страницы с помощью JavaScript и, например, отправлять ее на сервер, закодировав посредством JSON. Может быть, не очень безопасно, но такой вариант тоже может работать, когда нам нужны именно наши cookie или наши возможности.
Вопрос:
—Передаются HTTP-only cookie?
Евгений Лисицкий:
— Да. Передаются HTTP-only cookie, совершенно верно.
Вопрос:
— Даже если у нас тот же самый домен?
Евгений Лисицкий:
— Нет, если у нас тот же самый домен, то эти cookie уйдут автоматом в том же самом GET-запросе, когда у нас шло установление соединения.
По HTTP-referer был вопрос. Видимо, разработчики так решили, что его имеет смысл оставить для старых целей, и сформировать отдельный заголовок, чтобы не было пересечений.
Вопрос:
— Здравствуйте! У меня такой вопрос по поводу клиентсайда. Насколько я знаю, поддержка WebSocket появилась в Chrome последней версии. Как обстоят дела с хаками для предыдущих версий браузеров? Насколько я знаю, используется какой-то back-end на flash для общения с сервером. Так ли это?
Евгений Лисицкий:
— Да, так. Спасибо за вопрос! Действительно, нативная поддержка на сегодня есть только в одном браузере — в последнем Chrome. Зимой это было только в девелоперской версии, сейчас, в принципе, стабильные ветки тоже поддерживаются.
Как быть с другими браузерами? На сегодня есть замечательная библиотека, которая называется websocket.js, которая как раз с помощью flash эмулирует всю эту работу. Дело состоит в том, что мы создаем крошечную (10-пиксельную буквально) flash’ку, эта flash’ка у нас открывает TCP-socket на наш сервер, а дальше можно общаться по протоколу websocket. То есть все так, как я и описал.
С одной стороны, это некоторая проблема, потому что опять же функциональность этой вещи на flash чуть меньше, чем у полноценной поддержки в браузере.
С другой стороны, она полностью моделирует интерфейс. Например, websocket написал код, и он у меня работает абсолютно одинаково как в Chrome, так и в Internet Explorer. Когда поддержка WebSocket уже будет реализована всеми браузерами, я просто уберу эту flash’ку, а весь код у меня остается рабочим.
Вопрос:
— Могли бы вы сравнить протокол WebSockets с Jabber и RTMP?
Евгений Лисицкий:
— Вообще это немного разные вещи. Насколько я знаю, Jabber, или, точнее, XMPP, - это расширяемый протокол для передачи сообщений. Он построен на базе XML. Туда вы можете добавлять что угодно — какие-то свои расширения и так далее. RTMP в больше степени, по-моему, ориентируется на медиа-данные.
Задача WebSocket — организация именно постоянного тоннеля и соединения сервера и клиента (в большей части случаев).
Вопрос:
— RTMP еще часто используется для создания flash-игрушек. Там именно держится постоянное соединение, там есть реестры для удаленных вызовов. То есть все то же самое.
Евгений Лисицкий:
— В принципе, да. Можно использовать RTMP. Но в чем плюс? В последнее время flash немного сдает свои позиции. То есть мы видим, например, позицию компании Apple, которая не спешит включать flash в свои новые устройства.
Здесь мы видим некий стандарт, который как раз может заменить flash. Отмечу, что у flash есть еще одна небольшая проблема. Дело в том, что у него совершенно по-своему сделана модель безопасности. Прежде чем flash сможет подключиться к вашему серверу, он должен загрузить политику безопасности.
Политика безопасности — это такой специальный XML-файл, который грузится с 843-гопорта. Да, где они взяли эту цифру, я не знаю. Почему-то пытаются ее стандартизировать. Либо с Socket, с порта назначения. Это создает проблему, потому что часто 843-й порт может быть банально закрыт на сервере, на каком-нибудь порт-сервере, на маршрутизаторе и так далее.
Вообще, знаете, у меня возникла такая мысль. Может быть, немного крамольная для flash-разработчиков. Но сейчас мы эмулируем работу WebSocket через Flash Socket, ибо Flash Socket дает нам больше возможностей. Но через некоторое время, когда WebSocket заработает в полную силу, я не исключаю, что даже flash будет гонять свои бинарные данные через него.
Почему? Потому что у нас есть серьезный задел.
Во-первых, преимущество в модели авторизации. Нам не нужны какие-то нестандартные порты.
Во-вторых, модель передачи сообщений. Если Flash Socket открывает соединение на какой-то порт и сервер, то он идет туда. Здесь, скажем, сервер вместо установления соединения по WebSocket может отдать ему HTTP-редирект и после этого браузер обратится на совсем другой порт.
Таким образом, можно будет сделать какую-то примитивную разгрузку. Раскидывание нагрузки на разные серверы back-end. Спасибо.
Вопрос:
— У меня 3 вопроса. Вопрос номер раз. Известно ли вам что-нибудь о нативной поддержке всего этого счастья в более распространенных браузерах, а именно в Internet Explorer, Firefox?
Вопрос номер 2. Что случится с WebSocket, если сеть пропадет на клиентском компьютере?
Вопрос номер 3. Известно ли вам что-нибудь о квазипромышленных решениях, построенных на WebSocket?
Евгений Лисицкий:
— Первый вопрос. Как я уже говорил, полноценная нативная поддержка на сегодня есть только в Chrome. Разработчики Firefox этим заинтересованы. Они обещали выпустить поддержку где-то в версии 3.7.
Что касается Internet Explorer, то вчера я специально задавал этот вопрос Алексу Могилевскому. Он мне толком не ответил, когда это будет поддерживаться. Я намеренно скачал документ IE9 technology preview. К моему огорчению, там нет поддержки WebSocket. Впрочем, может быть, будет к релизу, а может быть, в какой-нибудь 12-й или 15-й версии.
В любом случае, как вы, наверное, могли заметить, свой пример я демонстрировал как раз на Internet Explorer. Тут, правда, Интернет был не нативно, а через flash’ку.
Дальше. Что возникает при разрыве соединения? Вообще в сети может быть 2 вещи.
Обрыв может быть, скажем, тихий (в момент неактивности). Внезапно раз — обрыв, пропало все. Ни сервер, ни клиент не получили сообщения об этом. Монтер где-то там далеко перерезал проводок. Ближайший маршрутизатор об этом "знает", а все, кто дальше, "не знают".
Естественно, такое не обнаружится. Вернее, оно будет обнаружено в момент, когда пойдет передача сообщения и когда связь оборвется.
Когда обнаруживается disconnect, то просто срабатывает наша функция обратного вызова (callback onclose). Например, если я сейчас зайду в консоль и заглушу сервер, то на мониторах у всех, кто сейчас подключен, появится надпись: «WebSocket disconnected». Это вопрос корректного завершения работы.
Должен сказать еще одну вещь про API. Он пока неокончательно устоялся, и планируется еще один callback — onerror — который будет вызываться в момент возникновения различных ошибок (в том числе, сетевых). Я не стал его пихать, потому что это еще, как я понимаю, не окончательная редакция.
Третий вопрос повторите, пожалуйста?
Вопрос:
— Про нагруженные проекты.
Евгений Лисицкий:
— Я видел поддержку на одном из чатов, но это не промышленное решение...
Вопрос:
— Скорее развлекательное?
Евгений Лисицкий:
— Да, поиграться. Есть такая компания, как Kaazing, которая как раз занимается веб-проектами в режиме реального времени. У них есть решения для STOMP’a (Stream Text Oriented Messaging Protocol), есть, по-моему, Server-Send Events решения и сейчас они вовсю трубят о поддержке WebSocket.
Вопрос:
— Расскажите подробнее о платформе...
Евгений Лисицкий:
— Эта платформа сидит как Gate, она написана на Java, она одним концом подключается к каким-то вашим сервисам, принимает от них какие-то сообщения и через WebSocket передает их дальше вам. Спасибо.
Глеб Белогорцев, РБК:
— Вы можете рассказать подробнее, что должно быть на сервере для того, чтобы хотя бы такой замечательный чат работал?
Евгений Лисицкий:
— В принципе, вы можете использовать практически любой событийно-ориентированный веб-сервер. Я сейчас могу отмотать немного назад.
Здесь у меня обозначена масса технологий. Например, это может быть реализовано на JavaScript — тогда надо использовать NodeJS, на Python — берите Twisted, Tornado (причем Twisted уже объявили о том, что они поддерживают WebSocket — вы можете просто брать готовые решения и делать). Ruby — EventMachine. Есть даже решения на PHP — PHP демон.
Лично у меня все сделано на Erlang на базе Misultin. Почему? Просто он мне понравился. Компактный, легковесный веб-сервер.
Глеб Белогорцев, РБК:
— Что из них более стабильное? Что можно более-менее уверенно использовать?
Евгений Лисицкий:
— Вы знаете, к более стабильным и более промышленно готовым на сегодня я бы, наверное, отнес решения на Erlang. Почему? Потому что это язык, ориентированный именно на такие вещи.
Это и полноценная конкурентность процессов, это и изоляция процессов, и их надежность. Софт приближен к работе в режиме реального времени. Другие преимущества — это компактность решения и простота написания. Я думаю, что такое решение — чат — реализовать достаточно просто.
Через некоторое время я планирую даже выложить исходники. В принципе, тогда можно будет посмотреть. Я правду говорю: это не промышленное решение. Его применять не надо, потому что вы потом будете меня долго ругать (смеется). Это именно демонстрация технологии — именно такая, чтобы можно было просто взять и "пощупать".
Вопрос:
— Вы, видимо, сказали, что это применимо на браузере Chrome от Google. Очищенная версия Chrome (немецкая) тоже поддерживает WebSocket или как? То есть все версии? Или вы не проверяли?
Евгений Лисицкий:
— Вы знаете, я тестировал на последней версии в продакшн. У меня, правда, Chrome русский, просто скаченный в виде DMG-шки с официального сайта. Какие изменения и особенности есть в локальных языковых версиях — я, скажу прямо, не знаю. Там я свой чат не тестировал.
Вопрос:
— Нет, это не локальная языковая версия. Это немецкая версия Chrome, которая очищена. Более общедоступная и очищенная от всяких нехороших вещей по архивации, по наблюдению за пользователями, которые есть в Google.
Евгений Лисицкий:
— Я понял вас. До этого я тестировал работу на Chromium (то есть общедоступном варианте Chrome под Ubuntu). Все работало на ура.

Комментарии

Нет ни одного комментария

Только пользователи могут оставлять комментарии

Возможно, вам будет интересно:

Владимир Бобриков

Владимир Бобриков

Руководитель НИОКР-а (Imhonet).

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

Антон Немцев

Антон Немцев

Независимый frontend-разработчик c 14-летним стажем, создатель Frontender Magazine, докладчик на WSD, представитель ВСТ в Украине.

Доклад с примерами использования 3D/2D/анимации с помощью CSS для создания эмоционального дизайна.

Евгения Фирсова

Евгения Фирсова

Руководитель отдела веб-интерфейсов, Яндекс.Деньги.

Евгения Фирсова (Яндекс) рассказывает о смене среды исполнения в проекте Яндекс.Деньги.