Aplikacja klient-serwer bez dedykowanego serwera

0

Witam!

W jaki sposób zorganizować pracę aplikacji sieciowej, której stan musi być zsynchronizowany z innymi użytkownikami i jednocześnie nie możemy polegać na klasycznej architekturze, w której mamy dedykowany serwer (koszty utrzymania infrastruktury itp.)? Aplikacja musi rozstrzygać problem modyfikacji współdzielonych obiektów jednocześnie przez dwóch lub więcej klientów. Mój pomysł na to jest następujący: początkowo mamy dwóch klientów, którzy nie są ze sobą połączeni. Jeden z nich próbuje połączyć się z drugim - w tym momencie nie istnieje jeszcze serwer, który rozstrzygałby konflikty (np. jednoczesna modyfikacja jakiegoś obiektu). O tym fakcie wiedzą obaj klienci, którzy na drodze np. losowania próbują ustalić, który z nich będzie serwerem. Po skończonym losowaniu tworzony jest obiekt serwera i cała komunikacja przekierowywana jest do niego. W przypadku gdy do naszej "sesji" chcemy zaprosić kolejnego klienta stosowna informacja wysyłana jest do serwera przez jednego z obecnych już klientów, a serwer decyduje czy takie połączenie nawiązać. Teraz przypadek gdy klient chce dołączyć do trwającej już sesji: do dowolnego klienta uczestniczącego w sesji wysyłane jest zapytanie o możliwość dołączenia. Klient uczestniczący w sesji odsyła informację o tym, że sesja jest w trakcie i adres serwera, który zaakceptuje lub nie nowego klienta.

Nie mam absolutnie żadnego doświadczenia jeśli chodzi o projektowanie aplikacji działających przez sieć. Fragment z losowaniem serwera jest "zmałpowany" z OSPF'a. Cała ta architektura wydaje mi się bardzo mocno naciągana ale to jedyne co przyszło mi do tej pory do głowy.

Pozdrawiam!

0

Tak na szybko napisze, co mi przyszło do głowy po przeczytaniu twojego pomysłu:

Po pierwsze - musisz się liczyć z tym, że serwer może w każdej chwili zniknąć i to bez uprzedzenia. W związku z tym pozostałe komputery powinny u siebie posiadać kopie ważnych informacji, żeby w razie czego umieć przejąć rolę serwera.

Po drugie - żeby uniknąć zamieszania po zniknięciu serwera, aktualny serwer powinien posiadać i udostępniać klientom listę swoich następców. Po zniknięciu serwera pierwszy z listy przejmuje szefowa ie ;)

Trzecia sprawa - czy jakieś dane będą przechowywane albo przetwarzane? Bo inaczej się podchodzi się do jakiegoś czata, który ma umożliwić komunikacje w czasie rzeczywistym, a inaczej np.program magazynowy. Jeśli mamy jeszcze uwzględnić dane, to robi się ciężko.

Po czwarte - wyobraź sobie sytuację, w której masz 10 użytkowników, siedzą w dwóch pokojach po 5 w każdym. Nagle ktoś przez przypadek odpina zasilanie switcha na korytarzu, w efekcie czego pokoje tracą że sobą komunikację. W części, w której jest pierwotny serwer wszystko zostaje po staremu, tylko ubyło userów. W drugim powstaje nowy serwer, a tamci zostają do niego podłączeni. Po jakimś czasie ktoś zauważa awarię switcha i podłącza zasilanie. Oba pokoje znowu są razem. Mamy dwa serwery, a do tego na każdym z nich są inne dane, użytkownicy wykonali inne działania. Jak to połączyć?

0

Odpowiadając również na szybko i odnosząc się do Twojego posta...

Ad 1.
Każdy z komputerów będzie posiadać uzgodniony ze wszystkimi innymi użytkownikami i, co ważniejsze, serwerem stan. W przypadku zniknięcia serwera każdy z komputerów będzie w stanie przejąć jego rolę.

Ad 2.
Można zrobić listę tak jak Ty proponujesz lub po prostu ponownie przeprowadzić "wybory" serwera tylko tym razem z większą ilością użytkowników. Pozostaje kwestia ustalenia metryki.

Ad 3.
Dane będą ulegać ciągłej modyfikacji i w skrajnym przypadku dwóch klientów może zmodyfikować ten sam obiekt. Serwer jest w pewnym sensie mediatorem, który ma rozstrzygać takie konflikty i informować o wyniku sporu wszystkich klientów (ta część jest do dopracowania jeszcze). Ze względu na szybkość zmian żadna baza danych tutaj nie wchodzi w grę.

Ad 4.
Myślałem o zaimplementowaniu mechanizmu czegoś na kształt sumy kontrolnej ze stanu klientów i serwera. W przypadku niezgodności sum serwer narzuca klientowi swoją wizję danych a sam klient musi ją zaakceptować. W opisanym przypadku podziału i połączenia ponownie dwóch sieci możemy odpytywać klientów czy wiedzą coś o jakimś innym serwerze ale to jest kolejny pomysł "na szybko".

0

Jesteś pewny że baza danych akurat tutaj będzie wąski gardłem, a nie komunikacja po sieci?
Bo te wszystkie problemy/scenariusze które opisałeś, są identyczne jak dla rozproszonych baz danych nosql ...
i ktoś już te problemy rozwiązał :).

Swoją drogą robię coś podobnego obecnie w pracy, rozproszony system w którym każdy z węzłów posiada całą kopię danych i się synchronizują ze sobą kilka razy dziennie.
Tyle że ja do synchronizacji wykorzystuję centralną bazę danych, mam zamiar przepuszczać przez nią kilkadziesiąt tysięcy eventów dziennie. Także pomyśl o event sourcingu, bo niemodyfikowalne eventy które tylko mogę przybywać łatwiej się synchronizuje.

0

Akurat wiem, że baza danych tutaj to bardzo słaby pomysł, ponieważ całość ma być real-time ;) Całość odpowiada raczej specyfice gry multiplayer.

0

zobacz blockchain w bitcoinach

1

Zamierzasz to wszystko z ręki zakodować? No to będziesz musiał się zamknąć w piwnicy na miesiąc.

Łap link, ściągnij sobie darmowy egzemplarz:
https://www.distributed-systems.net/index.php/books/distributed-systems-3rd-edition-2017/

0
Kermit Żaba napisał(a):

Akurat wiem, że baza danych tutaj to bardzo słaby pomysł, ponieważ całość ma być real-time ;) Całość odpowiada raczej specyfice gry multiplayer.

Możesz użyć czegoś jak Etcd lub Consul do trzymania konfiguracji o aktualnym serwerze oraz wyborze serwera (leader election).

Choć na 90% jestem przekonany, że do twoich potrzeb centralny komponent albo klaster komponentów by wystarczył.
Jak zostało to zauważone, brzmi jak problemy związane z NoSQL, może Cassandra albo Riak by się sprawdziły.

0
Kermit Żaba napisał(a):

Odpowiadając również na szybko i odnosząc się do Twojego posta...

Ad 1.
Każdy z komputerów będzie posiadać uzgodniony ze wszystkimi innymi użytkownikami i, co ważniejsze, serwerem stan. W przypadku zniknięcia serwera każdy z komputerów będzie w stanie przejąć jego rolę.
...

Ad 3.
Dane będą ulegać ciągłej modyfikacji i w skrajnym przypadku dwóch klientów może zmodyfikować ten sam obiekt. Serwer jest w pewnym sensie mediatorem, który ma rozstrzygać takie konflikty i informować o wyniku sporu wszystkich klientów (ta część jest do dopracowania jeszcze). Ze względu na szybkość zmian żadna baza danych tutaj nie wchodzi w grę.

Słusznie koledzy zauwazyli, są to problemy podobne jak w rozproszonych bazach danych NoSQL ( tu uwaga, nie ma jednej bazy NoSQL, to bardzo rózne produkty - i różne koncepcje co do "głownego" węzła).
W tym świecie obowiazuje "CAP theorem" - albo szybkość, albo gwarancje itd... nie da się wszystkiego naraz.

Ad 4.
Myślałem o zaimplementowaniu mechanizmu czegoś na kształt sumy kontrolnej ze stanu klientów i serwera. W przypadku niezgodności sum serwer narzuca klientowi swoją wizję danych a sam klient musi ją zaakceptować. W opisanym przypadku podziału i połączenia ponownie dwóch sieci możemy odpytywać klientów czy wiedzą coś o jakimś innym serwerze ale to jest kolejny pomysł "na szybko".

Z biedą, a szczerze mówiąc to wcale, nie umiem sobie przedstawić realistycznie tej idei (choć rozumiem literki). Suma kontrolna ma niewiele co do kolejności, ich "priorytetu" itd..

NA PEWNO dobrze zaprojektowany model danych to podstawa w razie podmiany serwera. Teoria zna lepsze modele, jednym z tych, który teoretycznie znam :) jest "event sourcing".
Na jakie straty danych Cię stać?

0

Dane tracą ważność wraz z końcem sesji. Przez koniec sesji rozumiem, że wszyscy klienci, którzy byli podłączeni do serwera zakończą połączenia. Same sesje są raczej krótkie (do 2 godzin maksymalnie) i nie ma potrzeby zapisu ich przebiegu - liczy się tylko to żeby w danej chwili czasu wszyscy klienci jak i serwer mieli te same dane. Sama utrata danych nie będzie bolesna, ponieważ ich termin "przydatności" jest krótki a same dane zmieniają się bardzo dynamicznie.

0

Można użyć np. Kubernetesa. Node na każdej maszynie. Dane potrzebne do utrzymania sesji przechować w Redisie.
Można podejść z innej strony - to mi pasuje do rozwiązania peer-to-peer i zastosować hypermedia protocol IPFS.

2
Kermit Żaba napisał(a):

Witam!

W jaki sposób zorganizować pracę aplikacji sieciowej, której stan musi być zsynchronizowany z innymi użytkownikami i jednocześnie nie możemy polegać na klasycznej architekturze, w której mamy dedykowany serwer (koszty utrzymania infrastruktury itp.)?

Możesz zacząć od peer to peer jeśli zależy Ci na braku centralnego serwera - każdy jest serwerem i klientem jednocześnie :)

Synchronizację można rozwiązać nadając komunikatom znaczniki pozwalające określić kolejność ich nadawania (np. dwójka lokalny numer komunikatu + numer węzła, albo wektor lokalnych numerów komunikatów we wszystkich węzłach, jakie dany węzeł znał w chwili nadania komunikatu) i kolejkowanie ich przy odbiorze tak, by możliwe było dostarczanie komunikatów w odpowiedniej kolejności (porządek FIFO/przyczynowy/całkowity, do zapoznania się w dowolnym wykładzie z systemów rozproszonych)

Aplikacja musi rozstrzygać problem modyfikacji współdzielonych obiektów jednocześnie przez dwóch lub więcej klientów.

Algorytm Ricarta i Agrawali, algorytm Lamporta, kojarzę jeszcze jakąś modyfikację wykorzystującą przekazywanie żetonu ale nie pamiętam nazwy

O tym fakcie wiedzą obaj klienci, którzy na drodze np. losowania próbują ustalić, który z nich będzie serwerem. Po skończonym losowaniu tworzony jest obiekt serwera i cała komunikacja przekierowywana jest do niego.

Algorytmy elekcji: pierścieniowy i tyrana

1 użytkowników online, w tym zalogowanych: 0, gości: 1