08 August 2009

Outsourcing front end platforms & cross-domain issues

В статье описываются распространенные схемы интеграции веб-приложений со сторонними сервисами. Рассматриваются достоинства и недостатки различных вариантов построения аутсорсингового сервиса интегрируемого в веб-приложение на стороне клиента. Детально рассматриваются возможные проблемы реализации при встраивании сервиса с использованием JavaScript (DHTML). Дается общая характеристика нагрузки на сервис и ее особенности, а также общие советы по масштабированию.

Итак, аутсорсинговые front-end платформы. Аутсорсинг в общем – это оптимизация производства за счет передачи какого-либо бизнес процесса специализированным фирмам. Аутсорсинговый подход часто используется при разработке веб-ресурсов (только никто это не называет аутсорсингом).

Варианты интеграции сервисов

Например, вы разрабатываете какой-либо веб-сайт и вам необходимо добавить колонку новостей на первую страницу. У вас несколько вариантов реализации:

  1. Разработать CMS для новостей (либо использовать готовую) и нанять профессиональных журналистов.
  2. Разработать собственный краулер, который будет искать новости на просторах интернета по заданным критериям.
  3. Использовать поисковые системы общего назначения либо специализирующиеся на новостях.

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

Другой пример: вы управляете разработкой какого-то файл-хостинга. Основные функции вашего сайта – это найти и скачать какие либо файлы. И как дополнительная опция для видео – скачать в альтернативном формате. И снова у вас несколько возможных путей реализации с учетом ресурсоемкости этой функции:

  1. Использовать какие-то библиотеки кодирования/декодирования видео и запускать все операции на собственном сервере по запросу пользователя.
  2. Реализовать перекодировку видео с упреждением как некоторый cron (в случае небольшого количества поддерживаемых видео-форматов), с запуском процесса перекодировки:
    1. на собственных серверах;
    2. с использованием вычислительных мощностей какого-то cloud-computing центра;
    3. с полной передачей процесса перекодировке сторонней компании.

И опять-таки, два последних варианта – это аутсорсинг. В описанных выше примерах используется взаимодействие server-to-server. Пользователь никак не видит этого процесса. Вся реализация скрыта за вашими веб-серверами.

Другим примером использования аутсорсинга в интернете можно считать практически все платежные системы. Вряд ли кто-то при разработке интернет-магазина (пусть даже большого) решится на разработку собственной платежной системы. Обычно при нажатии на кнопке «оплатить» пользователь переадресовывается на сервисную страницу используемой платежной системы. Это – тоже аутсорсинг по своей сути. Мы передаем процесс оплаты сторонней организации. В приведенном примере услуги сторонней компании доступны пользователю как отдельные страницы.

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

Рассмотрим такой способ предоставления аутсорсинговых услуг – аутсорсинговые front-end платформы.

Выбор технологии

Итак, существует несколько возможных вариантов построения этого сервиса:

  • Встраивание Flash объектов (различные видео-хостинги, баннеры)
  • Встраивание сторонней страницы через IFrame (различные гаджеты, баннеры)
  • Встраивание путем вставки стороннего JavaScript-а (встраивание форм комментирования, всплывающих подсказок и т.п.)
  • Silverlight, Java Applets, и др.

Silverlight и Java апплеты не рассматриваются ввиду сравнительно низкой распространенности.

Встраивание Flash объектов позволяет вам использовать красивый сложный дизайн. Ваш функционал отделен от всей страницы. Вы можете взаимодействовать с основной страницей посредством выполнения JavaScript команд. Также у вас есть возможность взаимодействовать с любыми серверами, игнорируя ограничения same-origin policy в случае правильной настройки crossdomain.xml.

Использование IFrame полностью изолирует загруженный документ от основной страницы. Вы не можете взаимодействовать с основным документом, в результате различия в доменах («домен» в понимании same-origin policy – протокол + домен + порт). Как плюс вы можете использовать стандартные средства AJAX для взаимодействия с собственным сервером – никаких ограничений.

И крайний вариант (не последний, я учился в авиационном вузе :) – использование вставки JavaScript, который создает все необходимые элементы графического интерфейса. Этот способ предоставляет вам самые широкие возможности по взаимодействию с основной страницей. Вы можете делать все, начиная от встраивания собственных элементов UI до модификации страницы. Но у медали есть и обратная сторона:

  • Ваш код выполняется в контексте исполнения чужого сайта. Это означает, что у вас будут возникать конфликты с JavaScript объектами самого сайта.
  • Ваш HTML код (сгенерированный и встроенный в станицу средствами JS) наследует все стили, определенные в CSS правилах основной странице.
  • Ваш HTML код отображается во всех (!) возможных типах документов (DOCTYPE).
  • Вы очень ограничены во взаимодействии с собственным веб-сервером. AJAX в классическом понимании просто невозможен (по причине все того же cross-domain policy).

Несмотря на обилие недостатков, этот подход дает вам широкие возможности и интеграции с основной страницей.

AJAX + same-origin policy

Итак, одной из больших проблем является cross-domain policy. Не все так плохо как кажется, способы обхода этого ограничения:

  • Динамическая генерация <script> тегов;
  • Взаимодействие через скрытый IFrame;
  • Прокси- страница, загруженная в скрытый IFrame и взаимодействие с ней через location.hash;
  • Прокси- Flash объекты (Java, Silverlight, …).

Динамическая вставка Script-тегов позволяет вам генерировать запросы на любые домены. Вы можете использовать протокол JSONP для загрузки каких-либо данных. Для отправки данных вы имеете возможность использовать только GET запросы, а это влечет за собой такие ограничения:

  • Длина URL не может быть более ~2k (отличается для различных браузеров);
  • Проблемы с кэшированием.

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

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

Взаимодействие через IFrame позволяет вам генерировать как GET, так и POST запросы. Вы можете узнать о том, что запрос выполнился (через обработку события onload), но с каким результатом – нет. Для генерации POST запроса вам следует создать IFrame, сгенерировать в нем HTML форму (например, через document.write). Добавить в форму поля с информацией, которую нужно передать. Установить значение атрибута method в POST и вызвать метод submit(). Повторюсь, но вы не можете получить результат запроса.

Вы можете загрузить страницу-прокси с собственного домена в IFrame и использовать ее для выполнения некоторых команд. Для передачи команды необходимо изменять location.hash для IFrame из JavaScript основной страницы. Это не вызывает физической перезагрузки страницы, но внутренняя страница может отслеживать изменение значения location.hash и интерпретировать новые значения как команды/данные. Но, снова – взаимодействие одностороннее. Конечно, в ответ на команду JS из IFrame может изменить location.hash для основного документа – но увы, это может нарушить нормальную работу интегрированного сайта. Кроме того, описанный подход может вызвать проблемы с кнопкой «Назад» браузера.

DHTML Front-end платформы: проблемы верстки

Для уменьшения количества проблем с множеством DOCTYPE-ов стоит использовать табличную верстку. Таблицы более устойчивы к различным типам документов. Для предотвращения наследования CSS основного документа следует явно задать все свойства (можно не все – определяется опытным путем) с наивысшим приоритетом – в атрибутах style.

DHTML Front-end платформы: JavaScript конфликты

Конфликты JavaScript: конфликты могут возникнуть при совпадении имен глобальных переменных. Просто не используйте их. Создайте только одну глобальную переменную – пространство имен и все остальные объекты храните в ней. Также, конфликты могут возникнуть при использовании разных версий одного и того же JavaScript фреймворка. Старайтесь использовать фреймворки, использующие как можно меньше глобальных переменных. Как идеал – одну. Например, jQuery, YahooUI. В jQuery довольно просто модифицировать используемую глобальную переменную – пометите ее в собственном пространстве имен.

DHTML Front-end платформы: поддержание сессии

При реализации аутсорсинговой front-end платформы на основе встраивания JavaScript возникают проблемы с поддержанием HTTP сессии. Как известно, HTTP не поддерживает сессии, это stateless протокол. Для поддержания сессий необходимо использовать дополнительные средства, вот наиболее распространенные из них:

  • Скрытые поля в формах (hidden fields);
  • Дополнительный параметр запроса;
  • Cookies.

Все эти средства используются для хранения и передачи идентификатора сессии.

Скрытые поля форм не подходят, т.к. у нас нет возможности отправлять формы. Дополнительный параметр запроса требует ручного управления сессией на стороне клиента – ваш код должен «знать» о сессии и передавать ее идентификатор во всех запросах. Cookies – наиболее предпочтительный вариант, но с ним есть проблемы при передаче данных через вставку тега <script>. Дело в том, что не все браузеры поддерживают отправку/прием «3rd party cookies» - cookies при загрузке встроенных в страницу объектов. По умолчанию только MS IE и Safari не поддерживают 3rd party cookies. IE позволяет использовать их, если сервер отправляет специальный P3P заголовок ответа (response header).

Взято из Browser Security Handbook.

Front-end платформы: детальнее про нагрузку

Если рассмотреть аутсорсинговые front-end сервисы с точки зрения их разработки и поддержки, то несложно заметить очень большое отличие в динамике нагрузки от обычных веб-сайтов – количество запросов в единицу времени (далее просто нагрузка) равняется сумме нагрузки на все интегрированные веб-страницы.

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

Вы должны быть готовы к интеграциям с крупными веб-сайтами. Используйте минификацию (minification) или обфускацию (obfuscation) скриптов. Встраивайте ваш HTML и CSS в JavaScript с целью минимизации количества запросов к вашему веб-серверу. Переместите весь статический контент на «легкий» веб-сервер, например: Lighttpd, Nginx. Либо, еще лучше, используйте одну из CDN, например Akamai. Настройте глубокое кэширование для статического контента путем конфигурирования заголовков в ответе (response headers).

Заключение

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

Описанные варианты обхода ограничений кросс-доменного взаимодействия, а также особенности обработки 3rd party cookies не специфичны для аутсорсинговых платформ и относятся к front-end разработке в общем.

Полезные ссылки

  1. Wikipedia – outsourcing
  2. Browser Security Handbook
  3. jQuery + flXHR – Cross-Domain Ajax with Flash
  4. Yahoo UI Library: Cross-domain ajax sample
  5. P3P: Platform for Privacy Preferences Project
  6. Javascript.ru –толковые статьи по JavaScript

3 comments:

  1. Зачем использовать Akamai CDN, у которой нет ни одного сервера на просторах СНГ, когда в России появилась своя сеть CDN (см. http://ngenix.net)?

    ReplyDelete
  2. Согласен, для СНГ он не очень подходит. Тем не менее Akamai был использован только как пример, да и в статье ничего не говорится о геолокации интегрируемых сайтов. Для Европы - используейте Akamai, для СНГ - ngenix.net.
    P.S. Спасибо за информацию, не слышал про эту CDN.

    ReplyDelete
  3. ніасіліл многабукф(
    Був би безмежно вдячний, якщо у висновках було виписано які ж є методи кросдоменного аяксу з екзамплами.

    ReplyDelete

Profile