Как сэкономить при совместной работе в реальном времени

10

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

Некоторые решения, о которых я подумал:

  • Экономьте на каждом изменении. Мне не нравится это решение, потому что оно замедляет работу интерфейса и увеличивает нагрузку на БД.

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

Любые другие предложения будут полезны.

ОБНОВЛЕНИЕ: Изучив предлагаемое решение, Google Realtime API, я обнаружил, что:

  1. Пользователи вашего приложения должны иметь Google Drive и предоставлять вам доступ к своему диску . В лучшем случае это может представлять неудобный поток пользовательского интерфейса или препятствовать использованию функции реального времени пользователями, у которых нет Google Диска.

  2. Все настройки обмена, которые сделаны на вашей стороне, должны быть скопированы для документа Google.

ОБНОВЛЕНИЕ 2: чтобы достичь цели, я пошел с Google Firebase

dev.e.loper
источник
Почему разница между новым пользователем и уже активными пользователями, редактирующими / просматривающими один и тот же документ?
Энди
@ Энди Сейчас я транслирую через сокеты все изменения, которые вносят пользователи. Эти изменения обновляют пользовательский интерфейс для пользователей, у которых открыт браузер, но они не сразу сохраняются в базе данных. Поэтому у меня есть ситуация, когда новый пользователь присоединяется, он загружает документ из базы данных и не видит все последние изменения, которые еще не были сохранены.
dev.e.loper
1
если вы уже отправляете изменения и хотите оставить такое же поведение, как сейчас, вы можете попросить одного из клиентов отправить последнее представление новому клиенту или у вас может быть один виртуальный клиент на сервере, который получает все изменения, а когда новый клиент присоединяется, отправляет последние вид на это.
Дайний,

Ответы:

14

Гугл драйв

Если вы пытаетесь создать собственную версию документации Google, я советую вам взглянуть на Google Realtime API . Google недавно выпустил это с намерением позволить другим разработчикам использовать те же инструменты, что и для совместной работы в реальном времени. Это позволит вам сэкономить время на разработке и быстрее получить рабочий продукт.

Вы можете легко взять данные, содержащиеся в документе, и регулярно отправлять их в свою базу данных, или же сама база данных будет «участником» обмена, просто прослушивая и регистрируя все изменения. Это также позволяет пользователю определять свои собственные структуры данных, которые затем можно использовать в API реального времени, поэтому вы можете расширять его по своему усмотрению.

Не Google Диск

Итак, согласно вашему исследованию, Google Drive не вариант. Это хорошо, но это будет сложнее и, возможно, не сработает, в зависимости от того, сколько вы в него вложите.

Вот общая стратегия, которую я бы использовал для решения этой проблемы:

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

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

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

  4. Резервное копирование в базу данных через определенные промежутки времени. Решите, как часто вы хотите выполнять резервное копирование (каждые 5 минут или, может быть, каждые 50 изменений). Это позволяет вам поддерживать резервное копирование, которое вы хотите.

Проблемы: Это не идеальное решение, поэтому вот некоторые проблемы, с которыми вы можете столкнуться.

  1. Пропускная способность сервера может снизить производительность

  2. Слишком много людей, читающих / пишущих, могут перегрузить сервер

  3. Люди могут потерять синхронизацию, если сообщение потеряно, поэтому вы можете убедиться, что синхронизируете его регулярно. Это означает повторную отправку всего сообщения, что может быть дорогостоящим, но в противном случае люди могут не иметь один и тот же документ и не знать его.

Ampt
источник
Да, изменения передаются всем клиентам, и у них есть (надеюсь одна и та же) версия в браузере. Похоже, вы говорите, что обновление документа для каждого действия - это путь?
dev.e.loper
Или, по крайней мере, иметь регулярные таймфреймы синхронизации, где текущее состояние документа передается в фоновом режиме, чтобы убедиться, что все находятся на одной странице. Как часто это будет зависеть от того, как быстро люди будут менять документ. Таким образом, у вас уже есть устоявшийся метод отправки новых людей, а также возможность убедиться, что он никогда не расходится слишком сильно.
День
1
+1. Не усложняй жизнь. Google делает это хорошо без необходимости изобретать велосипед.
Нил
Сохраняет ли Google Realtime на Google Диске? Я хочу сохранить в своей базе данных, а не Google Drive.
dev.e.loper
@ dev.e.loper добавил в ответ некоторую информацию об этом.
День
3

Я бы порекомендовал 1 постоянную копию документа на сервере. Когда клиент подключается к серверу, вы запускаете UPDATEкоманду (и) для этого клиента со всеми изменениями.

Обновить WorkFlow

Пользователь вызывает инициирующее изменение -> Клиент отправляет UPDATEна Сервер -> Сервер отправляет UPDATEКлиентам

Жизнеспособные триггеры

  1. Пользователь нажимает Сохранить
  2. Пользователь выполняет определенную задачу
    • Завершает редактирование ячейки
    • Завершает редактирование предложения / абзаца / строки
  3. Пользователь нажимает Отменить
  4. Пользователь нажимает клавишу возврата
  5. Пользователь вводит ключ (сохранить при каждом изменении)

Обновить реализацию

Я хотел бы предложить возможность воссоздать документ с помощью ряда UPDATEкоманд, чтобы сервер сохранял каждое ОБНОВЛЕНИЕ, а при подключении нового клиента клиенту можно было отправлять серию обновлений, а сам он мог заново создавать документ для отображения на экране. Пользователь. Кроме того, в качестве альтернативы вы можете использовать SAVEотдельную команду, в которой UPDATE могут быть временными изменениями, которые можно использовать для UNDOзапросов, и SAVE сохранит их для повторного открытия, если сервер закрыт или все клиенты отключаются.

Корей Хинтон
источник
2
Как насчет разрешения конфликта? Что если два человека одновременно редактируют одну и ту же область текста? Кроме того, это, похоже, создает нагрузку на БД, чего ОП старался избегать. Это может быть жизнеспособным для того, что ему нужно, хотя.
День
@Ampt, я сделал электронную таблицу, используя эту модель, и для конфликтов каждая конкретная обновляемая задача была полностью заменена самой новой версией. Таким образом, последний, кто завершит редактирование ячейки, полностью заменит ранее обновленную ячейку без слияния.
Корей Хинтон
1
То есть одно предложение перезаписало бы другое, если бы это был, скажем, документ Word?
День
@ Извините, да, в качестве альтернативы вы можете реализовать способ блокировки того, над чем работаете, но я выбрал легкий путь.
Корей Хинтон
3

1) Посмотрите на Knockout.js

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

2) Смешайте это с SignalR, и теперь у вас будет возможность отправлять уведомления другим пользователям, работающим над документом. С их сайта:

SignalR также предоставляет очень простой высокоуровневый API для выполнения RPC между серверами (вызов функций JavaScript в браузерах ваших клиентов из кода .NET на стороне сервера) в вашем приложении ASP.NET, а также добавление полезных хуков для управления соединениями. Например, события подключения / отключения, группировка подключений, авторизация.

Поэтому вам нужно иметь несколько хуков на уровне вашей модели в Knockout.js, чтобы делать некоторые вызовы SignalR при каждом изменении. Другие клиенты получат уведомление от SignalR и затем внесут соответствующее изменение в свою копию Модели, которая вернется к их Представлению.

Это интересная комбинация двух фреймворков, и вы должны иметь возможность искать и собирать больше информации для обработки деталей.

Например, этот пример codeproject специально адресован Co Working UIs and Continuous Clientsтому, что вы пытаетесь сделать.

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

Этот пост блога выглядит как отправная точка в серии постов блога, в которых обсуждается использование двух пакетов, и контрастирует с традиционным подходом ASP.NET. Может предоставить некоторые моменты для рассмотрения при разработке вашего сайта.

Этот пост в блоге выглядит немного более простым и обеспечивает основу для объединения двух пакетов.

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


источник
2

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

Но внедрение OT является сложной задачей и требует много времени. Поэтому вы можете использовать внешнюю библиотеку, например http://sharejs.org/ .

быть решено
источник
1
Google Realtime API выполняет OT youtu.be/hv14PTbkIs0?t=14m20s Они делают это как на клиенте, так и на сервере. Я не мог получить четкий ответ от чтения документов ShareJS, но я предполагаю, что ShareJS делает OT как на клиенте, так и на сервере?
dev.e.loper
1

Это в основном зависит от типа ваших документов и от того, как ваши пользователи сотрудничают.

Однако я бы:

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

Преимущества:

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

Недостатки:

  • не в режиме реального времени - например, вы отправляете каждые 30 секунд, но за это время кто-то печатает 3 предложения.
  • больше сетевого трафика - зависит от ваших документов и совместной работы
  • возможно большие сессии
  • возможно большое вычислительное усилие, если много пользователей сотрудничают и делают много изменений
Энди
источник
1

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

Как вы, наверное, поняли, это сложная проблема! Есть несколько прагматичных решений:

  1. Измените требования вашего приложения, чтобы не допустить истинного одновременного редактирования. Изменения могут быть объединены, как с системами контроля версий, с результатами, переданными каждому клиенту. Вы можете создать это самостоятельно, но это будет хуже для пользователя.
  2. Передайте синхронизацию мутаций состояния на решение с открытым исходным кодом, которое интегрируется с существующей технологией. ShareDB является текущим лидером в этом пространстве. Он основан на операционной трансформации и используется по крайней мере в одной производственной системе. Это решит проблему сохранения, которая вас волнует, но не поможет с дополнительными функциями UX, обязательными для любого приложения для совместной работы.
  3. Используйте готовую платформу, такую ​​как Convergence (заявление об отказе: я основатель), чтобы справиться со всеми сложными для вас задачами. Вы также получите дополнительные инструменты для совместной работы в режиме реального времени, такие как отслеживание курсора / мыши, выбор и чат, чтобы быстро создать превосходный опыт совместной работы. Посмотрите этот вопрос для хорошего обзора всех существующих инструментов там.
alalonde
источник