JSON-RPC? Weź sprytny REST

JSON-RPC? Weź sprytny REST

Jestem pewien, że nagłówek wywołał zdrową reakcję - „no znowu się zaczęło…”. Ale pozwól, że zajmę Twoją uwagę na 5-10 minut, a postaram się nie zawieść Twoich oczekiwań.

Struktura artykułu będzie taka: bierze się stereotypowe twierdzenie i odkrywa „naturę” powstawania tego stereotypu. Mam nadzieję, że pozwoli to spojrzeć na wybór paradygmatu wymiany danych w Twoich projektach z nowej perspektywy.

Aby było jasne, czym jest RPC, proponuję rozważyć standard JSON-RPC 2.0. W przypadku REST nie ma jasności. I nie powinno być. Wszystko, co musisz wiedzieć o REST - jest nieodróżnialny od HTTP.

Zapytania RPC są szybsze i bardziej efektywne, ponieważ pozwalają na wykonywanie zapytań wsadowych.

Chodzi o to, że w RPC można w jednym zapytaniu wykonać wywołanie kilku procedur jednocześnie. Na przykład, stworzyć użytkownika, dodać mu awatar i w tym samym zapytaniu zasubskrybować go do kilku tematów. Tylko jedno zapytanie, a ile korzyści!

Rzeczywiście, jeśli masz tylko jeden węzeł backend, będzie to wydawało się szybsze przy zapytaniach wsadowych. Ponieważ trzy zapytania REST wymagają trzykrotnie więcej zasobów od jednego węzła do nawiązania połączeń.

JSON-RPC? Weź sprytny REST

Zauważ, że pierwsze zapytanie w przypadku REST musi zwrócić identyfikator użytkownika, aby móc wykonać kolejne zapytania. Co również negatywnie wpływa na ogólny wynik.

Jednak takie infrastruktury można spotkać raczej w rozwiązaniach in-house i Enterprise. W najgorszym przypadku, w małych projektach WEB. Jednak pełnoprawne rozwiązania WEB, a jeszcze nazwane HighLoad, nie powinny być budowane w ten sposób. Ich infrastruktura musi spełniać kryteria wysokiej dostępności i obciążenia. A sytuacja się zmienia.

JSON-RPC? Weź sprytny REST

Zielonym oznaczone są kanały aktywności infrastruktury w tym samym scenariuszu. Zauważ, jak teraz zachowuje się RPC. Zapytanie korzysta z infrastruktury tylko po jednym ramieniu od balansu obciążenia do backendu. Tymczasem REST wciąż przegrywa w pierwszym zapytaniu, ale nadrabia straty, wykorzystując całą infrastrukturę.

Wystarczy wprowadzić do scenariusza nie dwa zapytania na wzbogacenie, ale powiedzmy pięć lub dziesięć… i odpowiedź na pytanie „kto teraz wygrywa?” staje się nieoczywista.

Zalecam spojrzenie na problem z szerszej perspektywy. Na schemacie widać, jak wykorzystuje się kanały infrastruktury, ale infrastruktura nie ogranicza się tylko do kanałów. Ważnym elementem wysoko obciążonej infrastruktury są pamięci podręczne. Przejdźmy teraz do uzyskania jakiegoś artefaktu użytkownika. Kilka razy. Powiedzmy 32 razy.

JSON-RPC? Weź sprytny REST

Zobaczcie, jak znacznie "wzbogaciła się" infrastruktura w RPC, aby sprostać wymaganiom dużego obciążenia. Chodzi o to, że REST wykorzystuje całą moc protokołu HTTP w przeciwieństwie do RPC. Na przedstawionym schemacie ta moc jest realizowana przez metodę żądania — GET.

Metody HTTP mają, między innymi, strategie buforowania. Można się z nimi zapoznać w dokumentacji na HTTP. Dla RPC używane są żądania POST, które nie są uważane za idempotentne, co oznacza, że wielokrotne powtarzanie tych samych żądań POST może zwracać różne wyniki (na przykład po każdym wysłaniu komentarza pojawi się nowa kopia tego komentarza) (ClickHouse-Ninja/Proton).

W związku z tym RPC nie jest w stanie efektywnie korzystać z infrastrukturalnych pamięci podręcznych. Prowadzi to do konieczności "wwożenia" pamięci podręcznych oprogramowania. Na schemacie w tej roli przedstawiony jest Redis. Pamięć podręczna oprogramowania wymaga z kolei od programisty dodatkowej warstwy kodu i widocznych zmian w architekturze.

Obliczmy teraz, ile żądań "wygenerował" REST i RPC w rozważanej infrastrukturze?

Zapytania
Przychodzące
do backendu
do bazy danych
do pamięci podręcznej (Redis)
ŁĄCZNIE

REST
1/32*
1
1
0
3 / 35

RPC
32
32
1
31
96

[*] w najlepszym przypadku (jeśli lokalna pamięć podręczna jest używana) 1 zapytanie (jedno!), w najgorszym 32 przychodzące zapytania.

W porównaniu do pierwszego schematu różnica jest uderzająca. Teraz staje się oczywiste, jakie korzyści wynika z REST. Ale proponuję nie zatrzymywać się na osiągniętym. Rozwinięta infrastruktura obejmuje CDN. Często rozwiązuje on również problem przeciwdziałania atakom DDoS i DoS. Otrzymujemy:

JSON-RPC? Weź sprytny REST

Tutaj sytuacja w przypadku RPC staje się naprawdę dramatyczna. RPC po prostu nie jest w stanie delegować pracy związanej z obciążeniem CDN. Pozostaje jedynie liczyć na systemy przeciwdziałania atakom.

Czy można na tym zakończyć? I znów, nie. Metody HTTP, jak już wspomniano, mają swoją „magikę”. Nic dziwnego, że metoda GET jest najbardziej powszechnie używaną w Internecie. Zwróć uwagę, że ta metoda może odwoływać się do części treści, może ustalać warunki, które będą interpretowane przez elementy infrastruktury jeszcze przed przekazaniem kontroli do twojego kodu itd. Wszystko to umożliwia tworzenie elastycznych, zarządzanych infrastruktur, które mogą obsługiwać naprawdę duże przepływy zapytań. A w RPC ta metoda… jest ignorowana.

Dlaczego więc mit o tym, że zapytania batch (RPC) są szybsze, utrzymuje się? Osobiście wydaje mi się, że większość projektów nie osiąga takiego poziomu rozwoju, w którym REST może pokazać swoje atuty. Co więcej, w małych projektach chętniej ujawnia swoje słabości.

Wybór między REST a RPC nie jest subiektywną decyzją pojedynczej osoby w projekcie. Ten wybór powinien odpowiadać wymaganiom projektu. Jeśli projekt jest w stanie wydobyć z REST wszystko, co rzeczywiście może, i to jest naprawdę potrzebne, to REST będzie doskonałym wyborem.

Ale jeśli do uzyskania wszystkich korzyści REST trzeba zatrudnić w projekcie devopsów do dynamicznego skalowania infrastruktury, adminów do zarządzania infrastrukturą, architekta do zaprojektowania wszystkich warstw usługi WEB… a projekt w tym czasie sprzedaje trzy paczki margaryny dziennie… zatrzymałbym się na RPC, ponieważ ten protokół jest bardziej użyteczny. Nie wymaga głębokiej wiedzy o działaniu pamięci podręcznych i infrastruktury, a skupia programistę na prostych i zrozumiałych wywołaniach potrzebnych mu procedur. Biznes będzie zadowolony.

Zapytania RPC są bardziej niezawodne, ponieważ mogą wykonywać zapytania batch w ramach jednej transakcji.

Ta cecha RPC jest niewątpliwym plusem, ponieważ łatwiej jest utrzymać bazę danych w spójnym stanie. Z REST jest trudniej. Zapytania mogą przychodzić nie w kolejności na różne węzły backendowe.

Ta „wadliwość” REST jest odwrotną stroną jego zalety opisanej powyżej — zdolności efektywnego wykorzystania wszystkich zasobów infrastruktury. Jeśli infrastruktura jest źle zaprojektowana, a tym bardziej, jeśli źle zaprojektowana jest architektura projektu i bazy danych w szczególności, to rzeczywiście jest to duży problem.

Ale czy zapytania batch są tak niezawodne, jak się wydają? Rozważmy przypadek: tworzymy użytkownika, wzbogacamy jego profil o jakieś opis i wysyłamy mu SMS z sekretem do zakończenia rejestracji. Tzn. trzy wywołania w jednym zapytaniu batch.

JSON-RPC? Weź sprytny REST

Rozważmy schemat. Przedstawia on infrastrukturę z elementami wysokiej dostępności. Istnieją dwa niezależne kanały komunikacji z bramkami SMS. Ale… co widzimy? Podczas wysyłania SMS występuje błąd 503 — usługa tymczasowo niedostępna. Ponieważ wysyłka SMS jest zapakowana w zapytanie batch, całe zapytanie musi się cofnąć. Operacje w bazie danych są anulowane. Klient otrzymuje błąd.

Następna próba to loteria. Albo zapytanie znowu trafi na ten sam węzeł i znowu zwróci błąd, albo będzie szczęście i się powiedzie. Ale najważniejsze, że przynajmniej raz nasza infrastruktura pracowała bez sensu. Było obciążenie, a zysku brak.

Dobrze, wyobraźmy sobie, że się natrudziśmy (!) i przemyśleliśmy opcję, kiedy zapytanie może być częściowo pomyślnie zrealizowane. A resztę spróbujemy wykonać po jakimś czasie (Jakim? Decyduje frontend?). Ale loteria pozostała. Zapytanie o wysyłkę SMS z prawdopodobieństwem 50/50 znowu się nie powiedzie.

Zgódźcie się, z perspektywy klienta, usługa nie wydaje się tak niezawodna, jak byśmy chcieli… a co z REST?

JSON-RPC? Weź sprytny REST

REST znowu korzysta z "magii" HTTP, ale teraz z kodami odpowiedzi. W przypadku błędu 503 w bramce SMS, backend przekazuje ten błąd do load balancera. Otrzymując ten błąd, load balancer, nie zrywając połączenia z klientem, kieruje zapytanie do innego węzła, który poprawnie realizuje zapytanie. Tzn. klient otrzymuje oczekiwany rezultat, a infrastruktura potwierdza swoje wysokie miano „wysokodostępnej”. Użytkownik jest szczęśliwy.

I to jeszcze nie wszystko. Load balancer nie tylko otrzymał kod odpowiedzi 503. Ten kod w odpowiedzi, zgodnie z standardem, powinien być wzbogacony nagłówkiem „Retry-After”. Nagłówek daje do zrozumienia load balancerowi, że nie warto niepokoić tego węzła przez określony czas. A kolejne zapytania o wysyłkę SMS będą kierowane od razu do węzła, który nie ma problemów z bramką SMS.

Jak widzimy, niezawodność JSON-RPC jest przeceniana. Naprawdę łatwiej zorganizować spójność w bazie danych. Ale w takim przypadku ofiarą stanie się niezawodność systemu jako całości.

Wyjście jest w dużej mierze analogiczne do poprzedniego. Kiedy infrastruktura jest prosta, jasność JSON-RPC z pewnością jest jego zaletą. Jeśli projekt zakłada wysoką dostępność przy dużym obciążeniu, REST wydaje się bardziej odpowiednim, choć bardziej skomplikowanym rozwiązaniem.

Próg wejścia w REST jest niższy

Myślę, że powyższa analiza, obalająca utarte stereotypy o RPC, wyraźnie pokazała, że próg wejścia w REST jest z pewnością wyższy niż w RPC. Ma to związek z koniecznością głębokiego zrozumienia działania HTTP, a także wymaga wystarczającej wiedzy o istniejących elementach infrastrukturalnych, które można i należy stosować w projektach WEB.

Więc dlaczego wielu myśli, że REST będzie prostszy? Moim osobistym zdaniem ta pozorna prostota wynika z samych manifestów REST. Tzn. REST to nie protokół, a koncepcja… REST nie ma standardu, są pewne zalecenia… REST nie jest trudniejszy od HTTP. Pozorna wolność i anarchia przyciągają "wolnych artystów".

Z pewnością REST nie jest trudniejszy od HTTP. Ale sam HTTP to dobrze przemyślany protokół, który przez dekady udowodnił swoją skuteczność. Jeśli nie ma głębokiego zrozumienia samego HTTP, to o REST również nie można oceniać.

A o RPC – można. Wystarczy wziąć jego specyfikację. Czy więc potrzebujesz głupiego JSON-RPC? Или все же хитрый REST? Решать вам.

Szczerze mam nadzieję, że nie zmarnowałem twojego czasu.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster