habrahabr

Работа веб-проекта в условиях нестабильного подключения

  • воскресенье, 2 ноября 2014 г. в 02:11:00
http://habrahabr.ru/post/242161/

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

Рассмотрим 3 примера: интернет-магазин, кинотеатр и онлайн-плеер. Для магазина и кинотеатра так же идет разделение на 2 части — что делать на стороне пользователя и на стороне оператора/продавца.


Я не буду рассуждать из-за чего происходят проблемы с подключением и разделять их каким-либо образом. Так же, в рамках данной статьи, потеря подключения рассматривается как редкий случай, а не постоянное состояние. Для подобного функционирования требуется связь с сервером хотя бы раз в день. У каждой задачи есть множество вариантов её решить. Нет смысла писать «тут можно было просто в памяти хранить, незачем писать в LocalStorage», спасибо. Так же обращаю внимание что я специально не писал никакого кода в статье, т.к. в каждом случае требуется индивидуальный подход, да и с течением времени ограничения хранилищ или особенности работы браузеров могут меняться, но суть останется прежней.

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

Всё это будет работать в случае OnePageApplication, в иных случаях решения додумывайте сами :-)

Ситуации:


Интернет-магазин


Со стороны пользователя:


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

Оператор


Оператору имеет возможность на отдельной странице посмотреть заказы «в процессе», так же получает сообщения о потерявших связь клиентах. Если пользователь был авторизован, то ему можно перезвонить (прямо в браузере), либо по получению звонка с добавочным номером АТСка сразу выводит данные о заказе. Все довольны.

Кинотеатр


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

Со стороны кассира:


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

Со стороны клиента при покупке онлайн.


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

Онлайн-плеер


Сейчас многие отказываются от коллекций музыки на жестком диске в пользу онлайн прослушивания. Казалось бы, сплошные плюсы — место на диске не кончается, пополнить коллекцию можно в пару кликов, она всегда есть на всех устройствах.
Но вот отключается интернет, и ты сидишь без музыки. Не круто.
Как вам вариант что, например, «любимые» треки всегда доступны? Уже лучше, когда есть, хотя бы, пара сотен треков.

Реализация


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

Как определить, что клиент (пользователь, АРМ оператора) отвалились?
Да точно так же. Конечно нужно дать хотя бы пару секунд на переподключение, прежде чем впадать в панику.

Онлайн плеер


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

В каком виде хранить треки?
Base64 или любое текстовое представление файла.

Как воспроизводить из строки?
Самый простой способ это просто генерация audio элемента с указанием в качестве источника “data:audio/wav;base64, …”. Есть масса библиотек, найти их не составит труда.

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

Так, хорошо, и где нам это хранить?
Вот тут уже сложнее. В зависимости от ситуации (браузера, устройства и т.п.) нам нужно использовать разные хранилища.
IndexedDB: firefox и chrome на мобильных устройствах, chrome, firefox, IE на десктопах
WebSQL: android browser, safari, ios web view на мобильных, safari на десктопах
SessionStorage для android browser, если 200мб websql недостаточно. Но нужно учитывать, что сохранение идет только на сессию.
Вообще, для мобильных устройств, лучше, конечно, выпускать приложение.

Что в итоге то?
У пользователя отключился интернет, даём доступ на страницу с любимыми треками / плейлистами, играем из хранилища по запросу :-)

Кинотеатр


Для кассы


Задача: работать при отсутствии подключения к основному сервису.

Какие данные хранить?
Информация о сеансах на пару дней, проданные билеты, «прогнозируемые» продажи онлайн, места, отведенные под онлайн билеты в случае потери подключения.

Где хранить?
В данном случае LocalStorage с 5мб должно хватить более чем.

Механизм работы
Потеряно подключение -> ограничиваем места в интерфейсе, помечаем проданные билеты флагом что они не сохранены. Для оператора, в целом, ничего не меняется. При появлении подключения отправляем обновлённые данные, получаем данные о проданных онлайн билетах и сеансах на ближайшие пару днейю

На сайте (при недоступности кассы)


Задача: не продавать билеты, которые могут быть проданы на кассе.

Решение: Заранее помечаем прогнозируемое количество мест как «онлайн покупки», в случае потери соединения продаем только их или предлагаем возможность позвонить кассиру.

На сайте (при обрыве связи клиента)


Задача: показать секту сеансов, цены, телефоны для бронирования.

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

Интернет-магазин


На клиенте


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

На сервере


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

Итог


Решать, стоит ли внедрение таких систем затрат, конечно же вам.
Главный плюс — пользователю не надо устанавливать никакого дополнительного ПО, надстроек и т.п. Всё сразу же работает.
С удовольствием отвечу на вопросы и расскажу про более конкретные реализации.