Mam stronę internetową, która pokazuje dużą ilość danych z serwera. Komunikacja odbywa się za pośrednictwem Ajax.
Za każdym razem, gdy użytkownik wchodzi w interakcję i zmienia te dane (powiedzmy, że użytkownik A zmienia nazwę), nakazuje serwerowi wykonanie działania, a serwer zwraca nowe zmienione dane.
Jeśli użytkownik B uzyska dostęp do strony w tym samym czasie i utworzy nowy obiekt danych, ponownie poinformuje o tym serwer za pośrednictwem ajax, a serwer zwróci nowy obiekt dla użytkownika.
Na stronie A mamy dane z obiektem o zmienionej nazwie. A na stronie B mamy dane z nowym obiektem. Na serwerze dane mają zarówno obiekt o zmienionej nazwie, jak i nowy obiekt.
Jakie są moje opcje utrzymywania synchronizacji strony z serwerem, gdy wielu użytkowników korzysta z niego jednocześnie?
Raczej unika się takich opcji, jak blokowanie całej strony lub zrzucanie całego stanu dla użytkownika przy każdej zmianie.
Jeśli to pomaga, w tym konkretnym przykładzie strona internetowa wywołuje statyczną metodę sieciową, która uruchamia procedurę składowaną w bazie danych. Procedura składowana zwróci wszystkie dane, które zmieniła, i nie więcej. Statyczna metoda web następnie przekazuje klientowi powrót procedury składowanej.
Edycja zleceń:
Jak zaprojektować aplikację internetową dla wielu użytkowników, która używa Ajax do komunikacji z serwerem, ale pozwala uniknąć problemów ze współbieżnością?
To znaczy równoczesny dostęp do funkcjonalności i danych w bazie danych bez ryzyka uszkodzenia danych lub stanu
Odpowiedzi:
Przegląd:
Cześć Raynos,
Nie będę tutaj omawiał żadnego konkretnego produktu. To, o czym wspominali inni, to dobry zestaw narzędzi, na który warto już spojrzeć (może dodać node.js do tej listy).
Z architektonicznego punktu widzenia wydaje się, że masz ten sam problem, który można zobaczyć w oprogramowaniu do kontroli wersji. Jeden użytkownik sprawdza zmianę obiektu, inny użytkownik chce zmienić ten sam obiekt w inny sposób => konflikt. Musisz zintegrować zmiany użytkowników w obiektach, jednocześnie będąc w stanie dostarczać aktualizacje w odpowiednim czasie i wydajnie, wykrywając i rozwiązując konflikty, takie jak ten powyżej.
Gdybym był w twoich butach, rozwinąłbym coś takiego:
1. Po stronie serwera:
Określ rozsądny poziom, na którym możesz zdefiniować coś, co nazwałbym „artefaktami atomowymi” (strona? Obiekty na stronie? Wartości wewnątrz obiektów?). Będzie to zależeć od serwerów WWW, sprzętu do obsługi baz danych i pamięci podręcznej, liczby użytkowników, liczby obiektów itp. Nie jest to łatwa decyzja.
Dla każdego artefaktu atomowego masz:
Serwer lub komponent pseudoserwera, który jest w stanie skutecznie dostarczać odpowiednie dzienniki zmian do podłączonego użytkownika. Observer-Pattern jest twoim przyjacielem.
2. Po stronie klienta:
Klient javascript, który może mieć długotrwałe połączenie HTTP z powyższym serwerem lub używa lekkiego odpytywania.
Komponent aktualizujący artefakty javascript, który odświeża zawartość witryn, gdy podłączony klient javascript powiadamia o zmianach w historii obserwowanych artefaktów. (znowu wzór obserwatora może być dobrym wyborem)
Komponent kodujący artefakty javascript, który może zażądać zmiany artefaktu atomowego, próbując uzyskać blokadę mutex. Wykrywa, czy stan artefaktu został zmieniony przez innego użytkownika zaledwie kilka sekund wcześniej (opóźnienie klienta javascript i czynniki procesu zatwierdzania), porównując znany identyfikator-wersji-artefaktu po stronie klienta i bieżący identyfikator-wersji-artefaktu po stronie serwera.
Narzędzie do rozwiązywania konfliktów w javascript pozwalające na podjęcie decyzji przez człowieka, która-zmiana jest właściwą. Możesz nie chcieć po prostu powiedzieć użytkownikowi „Ktoś był szybszy od Ciebie. Usunąłem Twoją zmianę. Idź płakać”. Wydaje się, że możliwych jest wiele opcji spośród raczej technicznych różnic lub bardziej przyjaznych dla użytkownika rozwiązań.
Więc jak by to potoczyło ...
Przypadek 1: diagram rodzaju sekwencji do aktualizacji:
Przypadek 2: Teraz do popełnienia:
Przypadek 3: dla konfliktów:
Kilka słów o wydajności i skalowalności
Polling HTTP a „push” HTTP
skalowanie zaplecza
skalowanie frontendu
„kreatywne” poprawki
Cóż, mam nadzieję, że może to być początek własnych pomysłów. Jestem pewien, że możliwości jest dużo więcej. Z zadowoleniem przyjmuję krytykę lub ulepszenia tego posta, wiki jest włączone.
Christoph Strasen
źródło
Wiem, że to stare pytanie, ale pomyślałem, że po prostu do niego zadzwonię.
OT (przekształcenia operacyjne) wydają się dobrze pasować do wymagań dotyczących jednoczesnej i spójnej edycji dla wielu użytkowników. Jest to technika używana w Dokumentach Google (i była również używana w Google Wave):
Istnieje biblioteka oparta na JS do używania transformacji operacyjnych - ShareJS ( http://sharejs.org/ ), napisana przez członka zespołu Google Wave.
A jeśli chcesz, istnieje pełna struktura sieciowa MVC - DerbyJS ( http://derbyjs.com/ ) zbudowana na ShareJS, która zrobi wszystko za Ciebie.
Używa BrowserChannel do komunikacji między serwerem a klientami (i uważam, że obsługa WebSockets powinna być w toku - była tam wcześniej przez Socket.IO, ale została usunięta z powodu problemów dewelopera z Socket.io). w tej chwili jednak nieliczne.
źródło
Rozważyłbym dodanie zmodyfikowanej pieczęci opartej na czasie dla każdego zbioru danych. Tak więc, jeśli aktualizujesz tabele db, należy odpowiednio zmienić zmodyfikowany znacznik czasu. Korzystając z AJAX, możesz porównać zmodyfikowany znacznik czasu klienta z sygnaturą czasową źródła danych - jeśli użytkownik jest kiedykolwiek z tyłu, zaktualizuj wyświetlacz. Podobnie jak w przypadku tej witryny, która okresowo sprawdza pytanie, aby sprawdzić, czy ktoś inny odpowiedział, gdy wpisujesz odpowiedź.
źródło
Musisz użyć technik push (znanych również jako Comet lub reverse Ajax), aby propagować zmiany do użytkownika, gdy tylko zostaną wprowadzone do bazy danych. Wydaje się, że najlepszą obecnie dostępną techniką jest długie sondowanie Ajax, ale nie jest ono obsługiwane przez każdą przeglądarkę, więc potrzebne są rozwiązania awaryjne. Na szczęście istnieją już rozwiązania, które sobie z tym poradzą. Wśród nich są: orbited.org oraz wspomniany już socket.io.
W przyszłości będzie łatwiejszy sposób na zrobienie tego, który nazywa się WebSockets, ale nie jest jeszcze pewne, kiedy ten standard będzie gotowy na czas największej oglądalności, ponieważ istnieją obawy dotyczące bezpieczeństwa dotyczące obecnego stanu standardu.
W bazie danych z nowymi obiektami nie powinno być problemów ze współbieżnością. Ale kiedy użytkownik edytuje obiekt, serwer musi mieć jakąś logikę, która sprawdza, czy obiekt został w międzyczasie edytowany lub usunięty. Jeśli obiekt został usunięty, rozwiązanie jest znowu proste: po prostu odrzuć edycję.
Ale najtrudniejszy problem pojawia się, gdy wielu użytkowników edytuje ten sam obiekt w tym samym czasie. Jeśli użytkownik 1 i 2 rozpoczną edycję obiektu w tym samym czasie, obaj dokonają edycji tych samych danych. Powiedzmy, że zmiany wprowadzone przez użytkownika 1 są najpierw wysyłane na serwer, podczas gdy użytkownik 2 nadal edytuje dane. Masz wtedy dwie możliwości: Możesz spróbować scalić zmiany Użytkownika 1 z danymi Użytkownika 2 lub możesz powiedzieć Użytkownikowi 2, że jego dane są nieaktualne i wyświetlić mu komunikat o błędzie, gdy tylko jego dane zostaną wysłane na serwer. Ta ostatnia opcja nie jest tutaj zbyt przyjazna dla użytkownika, ale ta pierwsza jest bardzo trudna do wdrożenia.
Jedną z nielicznych implementacji, która po raz pierwszy sprawiła , że to dobrze, był EtherPad , który został przejęty przez Google. Wydaje mi się, że użyli wtedy niektórych technologii EtherPad w Google Docs i Google Wave, ale nie mogę tego powiedzieć na pewno. Google również obsługuje EtherPad, więc może warto to sprawdzić, w zależności od tego, co próbujesz zrobić.
Naprawdę nie jest łatwo robić to jednocześnie edytując rzeczy, ponieważ nie jest możliwe wykonywanie atomowych operacji w sieci z powodu opóźnień. Może ten artykuł pomoże ci dowiedzieć się więcej na ten temat.
źródło
Próba napisania tego wszystkiego samemu to wielka praca i bardzo trudno jest to zrobić dobrze. Jedną z opcji jest użycie struktury zbudowanej w celu synchronizacji klientów z bazą danych i między sobą w czasie rzeczywistym.
Odkryłem, że platforma Meteor robi to dobrze ( http://docs.meteor.com/#reactivity ).
„Meteor obejmuje koncepcję programowania reaktywnego. Oznacza to, że możesz napisać kod w prostym, imperatywnym stylu, a wynik zostanie automatycznie przeliczony po każdej zmianie danych, od której zależy Twój kod”.
„Ten prosty wzorzec (obliczenie reaktywne + reaktywne źródło danych) ma szerokie zastosowanie. Programista jest oszczędzony przed pisaniem wezwań rezygnacji z subskrypcji / ponownej subskrypcji i upewnianiem się, że są one wywoływane we właściwym czasie, eliminując całe klasy kodu propagacji danych, który w przeciwnym razie zapchałby twój aplikacji z logiką podatną na błędy. "
źródło
Nie mogę uwierzyć, że nikt nie wspomniał o Meteorze . Z pewnością jest to nowy i niedojrzały framework (i oficjalnie obsługuje tylko jedną bazę danych), ale wymaga całej pracy i myślenia z aplikacji dla wielu użytkowników, jak opisuje plakat. W rzeczywistości NIE możesz budować aplikacji aktualizującej na żywo dla wielu użytkowników. Oto krótkie podsumowanie:
Meteor jest na tyle prosty, że sugerowałbym przynajmniej przyjrzeć się mu w poszukiwaniu pomysłów do kradzieży.
źródło
Te strony Wikipedii mogą pomóc w dodaniu perspektywy do uczenia się o współbieżności i współbieżnym przetwarzaniu w celu zaprojektowania aplikacji internetowej Ajax , która pobiera lub jest wypychana wiadomości o zdarzeniach stanu ( EDA ) we wzorcu przesyłania komunikatów . Zasadniczo wiadomości są replikowane do subskrybentów kanałów, którzy odpowiadają na zdarzenia zmiany i żądania synchronizacji.
Istnieje wiele form współbieżnego internetowego oprogramowania do współpracy .
Istnieje wiele bibliotek klienta API HTTP dla etherpad-lite , współpracującego edytora czasu rzeczywistego .
django-realtime -ground implementuje aplikację do czatu w czasie rzeczywistym w Django z różnymi technologiami czasu rzeczywistego, takimi jak Socket.io .
Zarówno AppEngine, jak i AppScale implementują API AppEngine Channel ; który różni się od Google Realtime API , którego przykładem jest googledrive / realtime-Playground .
źródło
Wypychanie po stronie serwera sposobem na to są techniki . Kometa jest (lub była?) Modnym słowem.
Konkretny kierunek, który wybierzesz, zależy w dużej mierze od stosu serwerów i tego, jak elastyczny jesteś / a. Jeśli możesz, przyjrzę się socket.io , który zapewnia implementację websockets w różnych przeglądarkach, co zapewnia bardzo usprawniony sposób dwukierunkowej komunikacji z serwerem, umożliwiając serwerowi wysyłanie aktualizacji do klientów.
W szczególności, zobaczyć ten pokaz przez autora biblioteki, co świadczy niemal dokładnie opisaną sytuację.
źródło