У меня есть веб-страница, на которой отображается большой объем данных с сервера. Связь осуществляется через ajax.
Каждый раз, когда пользователь взаимодействует и изменяет эти данные (скажем, пользователь A что-то переименовывает), он сообщает серверу выполнить действие, и сервер возвращает новые измененные данные.
Если пользователь B одновременно обращается к странице и создает новый объект данных, он снова сообщит серверу через ajax, и сервер вернется с новым объектом для пользователя.
На странице A у нас есть данные с переименованным объектом. А на странице B у нас есть данные с новым объектом. На сервере у данных есть как переименованный объект, так и новый объект.
Какие у меня есть варианты для синхронизации страницы с сервером, когда несколько пользователей используют ее одновременно?
Избегают таких опций, как блокировка всей страницы или выдача пользователю всего состояния при каждом изменении.
Если это помогает, в этом конкретном примере веб-страница вызывает статический веб-метод, который запускает хранимую процедуру в базе данных. Хранимая процедура вернет все данные, которые она изменила, и не более того. Затем статический веб-метод пересылает возвращенную хранимую процедуру клиенту.
Редактирование награды:
Как разработать многопользовательское веб-приложение, которое использует Ajax для связи с сервером, но избегает проблем с параллелизмом?
Т.е. одновременный доступ к функциям и данным в базе данных без риска повреждения данных или состояния.
Ответы:
Обзор:
Привет, Райнос,
Я не буду здесь обсуждать какой-либо конкретный продукт. То, что упоминали другие, - это хороший набор инструментов, на который уже стоит взглянуть (возможно, добавьте node.js в этот список).
С архитектурной точки зрения, у вас, похоже, та же проблема, что и в программном обеспечении для контроля версий. Один пользователь регистрирует изменение объекта, другой пользователь хочет изменить тот же объект другим способом => конфликт. Вы должны интегрировать изменения пользователей в объекты, в то же время имея возможность своевременно и эффективно доставлять обновления, обнаруживая и разрешая конфликты, подобные описанному выше.
Если бы я был на вашем месте, я бы разработал что-то вроде этого:
1. На стороне сервера:
Определите разумный уровень, на котором вы бы определили то, что я бы назвал «атомарными артефактами» (страница? Объекты на странице? Значения внутри объектов?). Это будет зависеть от ваших веб-серверов, базы данных и оборудования для кэширования, количества пользователей, объектов и т. Д. Решение непростое.
Для каждого атомарного артефакта есть:
Серверный или псевдосерверный компонент, который может эффективно доставлять соответствующие журналы изменений подключенному пользователю. Observer-Pattern - ваш друг в этом.
2. На стороне клиента:
Клиент javascript, который может иметь длительное HTTP-соединение с указанным выше сервером или использует упрощенный опрос.
Компонент средства обновления артефактов javascript, который обновляет содержимое сайтов, когда подключенный клиент javascript уведомляет об изменениях в отслеживаемой истории артефактов. (опять же, шаблон наблюдателя может быть хорошим выбором)
Компонент фиксации артефакта javascript, который может запрашивать изменение атомарного артефакта, пытаясь получить блокировку мьютекса. Он определит, было ли состояние артефакта изменено другим пользователем всего за несколько секунд до этого (латантность клиента javascript и факторы процесса фиксации), путем сравнения известного идентификатора версии артефакта на стороне клиента и идентификатора версии текущего артефакта на стороне сервера.
Средство разрешения конфликтов javascript, позволяющее человеку принимать правильное решение. Возможно, вы не захотите просто сказать пользователю: «Кто-то был быстрее вас. Я удалил ваше изменение. Иди плачь.». Многие варианты из довольно технических различий или более удобных решений кажутся возможными.
Так как бы он катился ...
Случай 1: вид диаграммы последовательности для обновления:
Случай 2: Теперь о фиксации:
Случай 3: для конфликтов:
Несколько слов о производительности и масштабируемости
HTTP-опрос против HTTP "проталкивания"
внутреннее масштабирование
масштабирование внешнего интерфейса
"творческие" настройки
Что ж, я надеюсь, что это может стать началом ваших собственных идей. Я уверен, что есть еще много возможностей. Я более чем приветствую любую критику или улучшения в этом посте, wiki включена.
Кристоф Стразен
источник
Я знаю, что это старый вопрос, но я подумал, что просто вмешаюсь.
OT (операционные преобразования) кажутся подходящими для ваших требований одновременного и последовательного многопользовательского редактирования. Это метод, используемый в Google Docs (а также в Google Wave):
Существует библиотека на основе JS для использования операционных преобразований - ShareJS ( http://sharejs.org/ ), написанная членом команды Google Wave.
И, если хотите, есть полноценная веб-инфраструктура MVC - DerbyJS ( http://derbyjs.com/ ), построенная на ShareJS, которая все сделает за вас.
Он использует BrowserChannel для связи между сервером и клиентами (и я считаю, что поддержка WebSockets должна быть в разработке - она была там раньше через Socket.IO, но была удалена из-за проблем разработчика с Socket.io) Документы для начинающих - это однако на данный момент немного скудно.
источник
Я бы подумал о добавлении измененной метки на основе времени для каждого набора данных. Итак, если вы обновляете таблицы db, вы должны соответствующим образом изменить измененную временную метку. Используя AJAX, вы можете сравнить измененную метку времени клиента с меткой времени источника данных - если пользователь когда-либо отстает, обновите отображение. Подобно тому, как этот сайт периодически проверяет вопрос, чтобы узнать, ответил ли кто-нибудь еще, пока вы набираете ответ.
источник
Вам необходимо использовать методы push (также известные как Comet или обратный Ajax), чтобы распространять изменения на пользователя, как только они вносятся в базу данных. Наилучшим доступным в настоящее время методом для этого является длинный опрос Ajax, но он поддерживается не всеми браузерами, поэтому вам нужны резервные варианты. К счастью, уже есть решения, которые справятся с этим за вас. Среди них: orbited.org и уже упомянутый socket.io.
В будущем появится более простой способ сделать это, который называется WebSockets, но пока неизвестно, когда этот стандарт будет готов к использованию в прайм-тайм, поскольку существуют проблемы безопасности в отношении текущего состояния стандарта.
В базе данных не должно быть проблем с параллелизмом с новыми объектами. Но когда пользователь редактирует объект, на сервере должна быть логика, которая проверяет, был ли объект отредактирован или удален тем временем. Если объект был удален, решение опять же простое: просто отмените правку.
Но самая сложная проблема возникает, когда несколько пользователей редактируют один и тот же объект одновременно. Если Пользователь 1 и 2 начнут редактировать объект одновременно, они оба будут редактировать одни и те же данные. Допустим, изменения, внесенные пользователем 1, сначала отправляются на сервер, в то время как пользователь 2 все еще редактирует данные. Затем у вас есть два варианта: вы можете попытаться объединить изменения пользователя 1 с данными пользователя 2 или вы можете сообщить пользователю 2, что его данные устарели, и вывести ему сообщение об ошибке, как только его данные будут отправлены на сервер. Последний вариант здесь не очень удобный, но первый очень сложно реализовать.
Одной из немногих реализаций, которые впервые действительно получили это право, был EtherPad , который был приобретен Google. Я полагаю, что они тогда использовали некоторые технологии EtherPad в Google Docs и Google Wave, но я не могу сказать это наверняка. Google также открывает источник EtherPad, так что, возможно, стоит взглянуть на него, в зависимости от того, что вы пытаетесь сделать.
Это действительно непросто сделать это одновременно с редактированием материала, потому что невозможно выполнять атомарные операции в сети из-за задержки. Возможно, эта статья поможет вам узнать больше по теме.
источник
Пытаться написать все это самому - большая работа, и сделать это очень сложно. Один из вариантов - использовать структуру, созданную для синхронизации клиентов с базой данных и друг с другом в реальном времени.
Я обнаружил, что фреймворк Meteor делает это хорошо ( http://docs.meteor.com/#reactivity ).
«Meteor поддерживает концепцию реактивного программирования. Это означает, что вы можете писать свой код в простом императивном стиле, и результат будет автоматически пересчитываться при изменении данных, от которых зависит ваш код».
«Этот простой шаблон (реактивные вычисления + реактивный источник данных) имеет широкое применение. Программисту не нужно писать вызовы отписки / повторной подписки и следить за тем, чтобы они вызывались в нужное время, устраняя целые классы кода распространения данных, которые в противном случае засоряли бы ваш приложение с логикой, подверженной ошибкам ".
источник
Не могу поверить, что никто не упомянул Метеор . Это новый и незрелый фреймворк (и официально поддерживает только одну БД), но он берет на себя всю тяжелую работу и продумывание многопользовательского приложения, как описано на плакате. Фактически, вы НЕ можете создать многопользовательское приложение для обновления в реальном времени. Вот краткое изложение:
Meteor достаточно прост, поэтому я предлагаю вам хотя бы взглянуть на него в поисках идей для кражи.
источник
Эти страницы Википедии может помочь добавить перспективу изучения параллельности и одновременных вычислений для проектирования AJAX веб - приложений , которые либо тянет или в толкаемых состояние события ( EDA ) сообщения в шаблоне обмена сообщениями . В основном сообщения реплицируются подписчикам канала, которые реагируют на события изменения и запросы синхронизации.
Существует множество форм параллельного программного обеспечения для совместной работы в Интернете .
Существует ряд клиентских библиотек HTTP API для etherpad-lite , редактора для совместной работы в реальном времени .
django-realtime-playside реализует приложение чата в реальном времени в Django с различными технологиями реального времени, такими как Socket.io .
И AppEngine, и AppScale реализуют API канала AppEngine ; который отличается от Google Realtime API , который демонстрируется googledrive / realtime-Playground .
источник
Здесь можно использовать методы push- уведомлений на стороне сервера . Комета - это модное слово (или было?).
Конкретное направление, которое вы выберете, сильно зависит от вашего серверного стека и от того, насколько вы / он гибкий. Если вы можете, я бы взглянул на socket.io , который обеспечивает кроссбраузерную реализацию веб-сокетов, которые обеспечивают очень простой способ двунаправленной связи с сервером, позволяя серверу отправлять обновления клиентам.
В частности, посмотрите эту демонстрацию автора библиотеки, которая почти точно демонстрирует описанную вами ситуацию.
источник