Framework do pisania rozproszonych aplikacji

1

Cześć!

Chciałem Wam zaprezentować narzędzie, nad którym pracuje od dość dawna - framework i orm w jednym, który pozwala pisać rozproszone aplikacje w C++.

Początkowa idea była dość zwięzła - obsłużyć jak najlepiej split brain dla środowisk klastrowych/cloud, z którymi pracowałem m.in. w IFJ PAN i Cyfronecie. Aplikacje działające w takich środowiskach miały pozostawać jak najdłużej "sprawne" po dowolnym podzieleniu klastra. W większości aplikacji zarządzających infrastrukturą, odcięcie dostępu do bazy albo pojedynczego serwisu powodowało dość duże problemy. Finalnie udało się to osiągnąć przez skopiowanie kilku pomysłów z blockchaina, X509 i architektury event driven wzorowanej na Androdzie.

Jak to działa? Pisząc aplikacje z dinemic, tak jak w przypadku wielu innych aplikacji tworzymy na początku model danych - klasy w C++ opisujące to, jak dane są trzymane w lokalnej bazie danych. W odróżnieniu od większości architektur, zamiast wystawiać serwer z API, które modyfikuje naszą baze danych, framework rozsyła multicastem aktualizacje stanu obiektów, którymi zarządza do innych aplikacji w sieci. Dzięki temu zmieniając pojedyncze pole w obiekcie, każdy w sieci wie co należy u zmienić w swojej lokalnej kopi bazy. Tak więc ORM z dinemic pośredniczy we wszystkich operacjach odczytu/zapisu do bazy i powiadami innych co i gdzie się zmienia. Żeby wszystko pozostało bezpieczne, każdy obiekt tworzy swoją parę kluczy, za pomocą których podpisywane są zmiany. Dzięki temu można też kontrolować kto do czego ma dostęp, poprzez odpowiednie szyfrowanie pól obiektów. Całość update'ów poszczególnych obiektów jest poukładana w łańcuchy, trochę na podobieństwo blockchaina. Dzięki temu po ewentualnym split brainie można odtworzyć wszystkie zmiany.

Oprócz ORM'a framework pozwala zdefiniować własne listenery, które są wywoływane gdy aplikacja (tzn my lub inna w sieci) przysyła update bazy danych. Może to dotyczyć aktualizowania danych w polach, całych obiektach lub na poziomie całego modelu danych. Dzięki nim można kontrolować co ktoś zmienia w naszej lokalnej bazie i, co chyba najważniejsze odpowiednio reagować na takie zmiany, np. dostosowując stan systemu lub zasobów do tego, co się zmienia w bazie.

Obecnie biblioteka jest dostępna na gitlabie jako open source, dla C++ oraz w formie wrappera, dla pythona. Całość można pobrać tu (binarki) i tu (źródła). Gdyby ktoś był zainteresowany, to dodaje jeszcze link do dokumentacji: https://dinemic.io/documentation/

W razie pytań chętnie odpowiem :)

0

Czyli po prostu jest to DB oparta o CRDT? Bo nie za bardzo rozumiem co tutaj jest "frameworkiem".

0
hauleth napisał(a):

Czyli po prostu jest to DB oparta o CRDT? Bo nie za bardzo rozumiem co tutaj jest "frameworkiem".

po części tak, natomiast dodaje sporo więcej - przede wszystkim zarządzanie uprawnieniami na poziomie pojedynczego obiektu, na bazie kluczy asymetrycznych i pozwala zdefiniować przez listenery jak sama synchronizacja ma się zachowywać.

A jeśli chodzi o to, co jest "frameworkiem", to przy użyciu dla programisty konieczne jest jedynie zdefiniowanie modeli, ich pól i ewentualnie listenerów. Poza tym całość synchronizacji pomiędzy nodami, zarządzanie uprawnieniami i warstwa kryptograficzna jest schowana pod tym narzędziem

0

Może po prostu rozpatrz pisanie tego w Google Go aka Golang.

0
Kumpel Kumpla napisał(a):

Może po prostu rozpatrz pisanie tego w Google Go aka Golang.

chyba łatwiej jest zrobić wrapper/przepisać z C/C++ na cokolwiek, niż z Golang na cokolwiek :) wiem, że Go teraz robi furorę, natomiast raz, to że go nie znam, a dwa to dużo narzędzi (zeromq, libsodium, redis) ma swoje implementacje w czystym C. W go na pewno za niedługo też będą, natomiast więcej wyboru było jeszcze jakiś czas temu dla C/C++.

2

Fajnie, ale czy nie praktyczniej byłoby użyć scentralizowanej kolejki/dziennika zdarzeń zamiast słać multicastem do wszystkich węzłów?

Kolejka sama w sobie powinna działać na kilku węzłach, używać czegoś jak raft czy paxos do uzyskania consensusu i przeżyć split brain jeżeli ma więcej niż połowę węzłów.

Dostęp do kolejki oczywiście po hoście, a nie IP, co pozwoli dodatkowo zrownoleglic obciążenie przez DNS load balancing, przynajnniej w przypadku odczytu. Jeżeli użyjesz czegoś jak kubernates to w zasadzie skalowanie i utrzymanie stanu kolejki oraz load balancing usługi (i to z poziomu klienta, czytaj bez DNS) masz załatwione od razu.

Odchodzi ci potrzeba bezposredniego monitorowania uczestników klastra (a skoro to miało przeżyć split brain to rozumiem że był jakiś protokół plotkowania albo heartbeat do mastera), możesz więc użyć rozwiązania z półki jak kubernates.

Są też gotowe systemy baz danych (nie relacyjnych), który przeżyją split brain, ponieważ oparte są na idei partycjonowania danych i ich replik, jak Cassandra czy Riak.

Samo c czy cpp nie jest językiem pierwszego wyboru dla aplikacji rozproszonych, chyba że pracuje się dla wielkiego korpo internetowego jak Facebook czy Google i ma się odpowiednia kadrę inżynierów i interes w tym by optymalizować na tak niskim poziomie, ewentualnie dla instytucji badawczej, która być może używa frameworki, które strach kijem dotykać. Takie zeromq jest napisane w c, ale udostępnia wrappery i/lub implementację natywne na multum języków i to jest jego siłą.
Redis z kolei nie narzuca języka programowania, udostępnia protokół (tekstowy).

Ciekawi mnie też kwestia węzła, który się na chwilę odłączy i dołączy z powrotem do klastra, np. przez błąd na poziomie sieci (np. padło chwilowo łącze, ktoś odłączył kabelek, transmisja TCP została zerwana przez jakieś urządzenie pośrednie, które wysłało rst zamiast odrzucic pakiety, albo nastąpił TCP timeout, w przypadku udp wystarczy, że segment nie dotarł do odbiorcy zanim się rozlaczyl). Może być z tyłu ze zdarzeniami i powinien nadrobić pobierając je od danego znacznika czasowego, hasha lub pobrać migawkę obecnego stanu. Jeżeli zdarzenia są rozsyłane multicastem, to kto ma historie lub cały stan by pomóc nadrobić stan temu nieszczęsnemu węzłowi.

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