stateless vs. stateful

0

Znalazłem fajny zbiór pytań na devops
https://github.com/bregman-arie/devops-exercises
ale patrzę i coś mi się nie zgadza

Explain stateless vs. stateful
Stateless applications don't store any data in the host which makes it ideal for horizontal scaling and microservices. Stateful applications depend on the storage to save state and data, typically databases are stateful applications.

Wg mnie stateless może trzymać dane w DB o ile ta DB nie jest powiązana z daną instancją - tzn. każda inna instancja może do tej DB pisać i czytać.

Stateless bym określił jako "instancje niezależne od siebie", albo "jeśli możesz dodać kolejną instancję w systemie i ona będzie poprawnie działać, będzie niezależna od pozostałych już istniejących albo powstałych w przyszłości instancji"

5

Stateless applications don't store any data in the host.

Czyli jak odpytujesz N razy te sama usługę, nie masz pewności, że zadanie będzie obsłużone przez tego samego hosta, ergo nie możesz trzymać lokalnie stanu (pamięć, dysk). Tu doczytaj: https://12factor.net/

2

A w tej bazie to niby co trzymasz jak nie stan czegoś?

2

Chyba po prostu nie zrozumiałeś tekstu. Piszą że przykładem aplikacji stateful są bazy danych, a nie aplikacje które korzystają z baz danych

Stateless applications don't store any data in the host
definicja jak dla mnie poprawna

0

No nie coś nie bardzo z tymi aplikacjami korzystającymi z bazy danych, o ile zawartość bazy zmienia się w czasie. Jak z klienta wywołasz jakieś GET https://costam.com/users to jeżeli ktoś tego użytownika doda, albo usunie, to będziesz mieć inną zwrotkę, bo zmienił się stan hosta (to, ze trzyma dane w DB, a nie w jakiejś tablicy nie ma znaczenia).

0
piotrpo napisał(a):

No nie coś nie bardzo z tymi aplikacjami korzystającymi z bazy danych, o ile zawartość bazy zmienia się w czasie. Jak z klienta wywołasz jakieś GET https://costam.com/users to jeżeli ktoś tego użytownika doda, albo usunie, to będziesz mieć inną zwrotkę, bo zmienił się stan hosta (to, ze trzyma dane w DB, a nie w jakiejś tablicy nie ma znaczenia).

chodzi o to że bijąc do różnych nodeów / mikroserwisów otrzymasz to samo. nie ma stanów wewnętrznych, wszystko co potrzeba przychodzi z zewnątrz w formie danych (może być z bazy danych) lub parametrów zapytania
wszystkie aplikacje które nie są readonly mają jakiś swój stan, jeśli stanem nazywasz zarejestrowanych użytkowników, ale nie o to w tym chodzi

0

@obscurity: Rozumiem to inaczej. To nie jest kwestia tego, że każdy serwis zwróci to samo, wtedy nadal mają stan, tylko go współdzielą. Prosta zasada bezstanowości, to wysyłasz 2 razy to samo żądanie, dostajesz dokładnie tę samą odpowiedź. To, że 5 instancji tego samego serwisu ma ten sam zmienny stan, to jeszcze nie znaczy, że tego stanu nie mają. Przykłady usług naprawdę bezstanowych - serwis który pobiera dane z kolejki, coś tam robi i wyrzuca do innej kolejki/zapisuje do db. Drugi serwis, który z tej bazy odczytuje liczbę zapisanych rekordów już będzie zwracał na każde żądanie inny stan (to, że przechowywany na zewnątrz, nie ma moim zdaniem znaczenia).

0

ja to rozumiem w ten sposób jaki jest opisany tutaj
https://www.xenonstack.com/insights/stateful-and-stateless-applications

i moim zdaniem nie ma znaczenia jak to rozumiemy tylko co chcemy osiągnąć
jedynie prawdziwą aplikacją bezstanową jest aplikacja serwująca statyczne treści czyli jakiś cdn a i tutaj można mieć wątpliwości co do definicji jeśli dopuszczamy uploadowanie nowych plików

jeśli chcemy mieć stateless serwisy żeby skalować aplikację w poziomie, tak jak w definicji z pierwszego posta to jak najbardziej chodzi tylko o to żeby nie trzymać stanu na pojedynczym węźle, a dane się mogą zmieniać pomiędzy zapytaniami, natomiast samo

jeśli chcemy mieć stateless żeby serwer proxy mógł cache'ować wyniki i żeby zapytania działały jak pure (czyste?) funkcje no to nie może być mowy o żadnym logowaniu, dokładaniu rzeczy do koszyka itp

jeśli chcemy mieć stateless po to żeby po prostu nie było stanu ale nie wiemy jakie są z tego korzyści no to fajnie, implementuj sobie jak chcesz, nazywaj jak chcesz

0
obscurity napisał(a):

ja to rozumiem w ten sposób jaki jest opisany tutaj

https://www.xenonstack.com/insights/stateful-and-stateless-applications

i moim zdaniem nie ma znaczenia jak to rozumiemy tylko co chcemy osiągnąć

Zgadza się

jeśli chcemy mieć stateless serwisy żeby skalować aplikację w poziomie, tak jak w definicji z pierwszego posta to jak najbardziej chodzi tylko o to żeby nie trzymać stanu na pojedynczym węźle, a dane się mogą zmieniać pomiędzy zapytaniami

Jasne, można ten stan współdzielić (wspólne żródło danych), albo synchronizować (każdy węzeł ma własny stan, ale dba o jego synchronizację z innymi)

jeśli chcemy mieć stateless żeby serwer proxy mógł cache'ować wyniki i działać jak czysta funkcja no to nie może być mowy o żadnym logowaniu, dokładaniu rzeczy do koszyka itp

Może - stan może być trzymany po stronie klienta i przesyłany jako parametr żądania.

0
piotrpo napisał(a):

jeśli chcemy mieć stateless żeby serwer proxy mógł cache'ować wyniki i działać jak czysta funkcja no to nie może być mowy o żadnym logowaniu, dokładaniu rzeczy do koszyka itp

Może - stan może być trzymany po stronie klienta i przesyłany jako parametr żądania.

ciężko by było zrobić w ten sposób obsługę sesji. Wylogowywanie byłoby chyba niemożliwe czy się mylę? Wystarczy nacisnąć przycisk wstecz i jesteśmy zalogowani.
Z koszykiem zgoda, da się to zrobić w pełni client-side

0

Z sesją, jak sam powiedziałeś - zależy co chcesz osiągnąć, właściwie to całe JWT sprowadza się do trzymania sesji po stronie klienta - jakaś usługa wystawia token zawierający twoją tożsamość, klient go przechowuje i wypuszcza z każdym żądaniem, a docelowy host ma sposób, żeby zweryfikować jego prawdziwość bez komunikacji z serwerem, który ten token wystawił. Wylogowanie może nastąpić poprzez "zapomnienie" tego tokenu przez klienta, albo poprzez przekroczenie czasu ważności tokenu (który również jest jego częścią). Natomiast nie da się prosto i czysto unieważnić tokenu od strony backendu.

1

Aplikacja bezstanowa nie trzyma danych między żądaniami - przykład HTTP. Serwer może zapisać jakieś dane (np. dane sesji) w bazie danych, a przy kolejnym żądaniu je odczytać. Ale stanowość polega na tym, że nie musi tego robić.

Czyli jeśli serwer HTTP miałby cały czas otwarte połączenie z klientem i przydzieloną dla niego pulę pamięci, w której trzymałby jego dane to byłaby aplikacja stanowa.

Aplikacje desktopowe są stanowe - stan aplikacji jest zapisywany w pamięci RAM Twojego komputera. Od uruchomienia, aż do zamknięcia aplikacji.

0
piotrpo napisał(a):

Z sesją, jak sam powiedziałeś - zależy co chcesz osiągnąć, właściwie to całe JWT sprowadza się do trzymania sesji po stronie klienta - jakaś usługa wystawia token zawierający twoją tożsamość, klient go przechowuje i wypuszcza z każdym żądaniem, a docelowy host ma sposób, żeby zweryfikować jego prawdziwość bez komunikacji z serwerem, który ten token wystawił. Wylogowanie może nastąpić poprzez "zapomnienie" tego tokenu przez klienta, albo poprzez przekroczenie czasu ważności tokenu (który również jest jego częścią). Natomiast nie da się prosto i czysto unieważnić tokenu od strony backendu.

@piotrpo Dosyć prosto zrobić zarządzanie sesją - po prostu musisz zrobić rejestr JWT tokenów na użytkownika (czyli jakbyś implementował sesję) a potem w aplikacjach / serwisach przy sprawdzaniu JWT niestety robić nadmiarowy request o weryfikację JWT do IdentityProvidera w systemie. W ten sposób np. będzies zmiał możliwość zrobienia wyloguj wszystkich.

Użycie JWT to dla mnie zysk też w innym miejscu - claimsach, gdzie możesz zrzucić metadane, które kosztują dodatkowe requesty do bazy danych dla obsługi requestów i mieć te dane w tokenie np. tabela ról użytkownika, metadane, lista ulubionych książek czy co tam będzie potrzebne. Przez co sumarycznie zmniejszy się koszta systemu.

1

Ciekawy temat bo jak widać interpretacje są różne. Zakładając to co już zostało wcześniej wymienione, a więc że aplikacja bezstanowa nie trzyma żadnych danych sesji w pamięci ani lokalnym dysku w celu łatwości skalowania horyzontalnego, to ja zastanawiam się nad jednym. Jak to się ma do jakiegoś cachowania w pamięci?

Mamy dwie instancje tego samego serwisu webowego. Poszedł request do serwisu A, serwis wyciągnął jakieś dane z bazy, dodał do lokalnego cache i zwrócił do klienta. Klient uderza tym razem do serwisu B, który wyciąga te same dane z bazy, przechowuje lokalnie w cache i zwraca do klienta. Kolejny request leci do A, i tym razem serwis zwraca dane z lokalnego cache. Z perspektywy klienta nic się nie zmienia, a fakt że raz dostał te same dane z serwisu A, później z B, a następnie znów z A ale tym razem z cache, na nic nie wpływają. Wszystko pozostaje transparentne.

Czy nadal mowa o stateless, czy jednak jest to statefull bo host przechowuje cache lokalnie? Czy może o statefull mowa tylko wtedy kiedy serwis ma dane potrzebne do obsłużenia kolejnych requestów od klienta, i wymagane jest sticky session w przypadku skalowania horyzontalnego?

1

Wymyśliłem coś takiego, może ma jakiś sens. Rozumiem stateful system jako taki system S, który spełnia warunek nazwijmy to sesji:

S.set(x);
assert S.get() == x;

Niezależnie, z którego node pobiorę wartość, zawsze będzie wynosić tyle, ile ustawiłem (po jakimś czasie T, bo ev. consistency).

Jeżeli to nie zachodzi dla jakiegoś scenariusza (np. dodanie, usuwanie node’ów), to system jest stateless - nie mam gwarancji, że jak zmienię stan na jakimś nodzie, to ten stan się zreplikuje.

Czyli wg. definicji przypadek z cache w ogólności jest stateless. Rzeczywiście tak jest, dane w cache mogą być outdated, przez co przy restartach dane mogą flapować (raz zwracana jest stara wartość z cache, a raz świeża z bazy).

Statelessy dają niższa gwarancje, ale dzięki temu są łatwiejsze w skalowaniu i HA. Nie trzeba utrzymywać sesji z wybranym nodem, nie trzeba implementować konsensusu itd

0

Dla mnie sprawa jest oczywista. Protokół HTTP jest bezstanowy. Aby dodać tam jakiś stan, robi się sesje. Tylko pamiętajmy, że stan sesji nie jest zapisywany w pamięci RAM, tylko w bazie/pliku. Przy kolejnym żądaniu musi być odczytany.

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