Wiele wywołań asynchronicznych a pojedyncze wywołanie interfejsu API

12

Pracujemy nad interfejsem API REST, który między innymi będzie używany przez interfejs HTML5 za pomocą javascript. Aplikacja jest przeznaczona do użytku w organizacji i zwykle ma około 300 użytkowników, ale chcemy dobrze skalować do około 1000 użytkowników.

Zwykle połączenia z interfejsem API będą wykonywane w sieci LAN, więc jakość i opóźnienie połączenia będą dobre, chociaż nie jest wykluczone sporadyczne korzystanie z Internetu, gdzie połączenia mogą być wolniejsze i z większym opóźnieniem przez 3G / 4G.

Dwie opcje, które pomyśleliśmy to:

  1. Interfejs wykona kilka jednoczesnych asynchronicznych wywołań interfejsu API, aby załadować różne komponenty interfejsu.

    • Plusy: Prostota.
    • Minusy: więcej połączeń z serwerem.
  2. Kontroler interfejsu wykona pojedyncze wywołanie interfejsu API, przekazując parametry, które obiekty należy pobrać.

    • Plusy: tylko jedno połączenie z serwerem, chociaż serwer nawiąże kilka połączeń z bazą danych.
    • Minusy: Wymaga mechanizmów zarówno w interfejsie użytkownika, jak i interfejsie API. To komplikuje projekt.

Dalsze objaśnienia: Będą różne zasoby ... / Produkt ... / Lokalizacje itp. Te zasoby można pobrać osobno, ale będą też inne zasoby abstrakcyjne ... / screen? Produkt i lokalizacje, które pobiorą oba w jednym połączeniu.

mattinsalto
źródło

Odpowiedzi:

14

Opcja 1 (wiele wywołań asynchronicznych) jest najlepszym wyborem, ponieważ:

  1. każde pojedyncze połączenie jest odrębną jednostką , więc możesz spróbować ponownie indywidualnie, jeśli coś się nie powiedzie. W monolitycznej architekturze „jednego wywołania”, jeśli jedna rzecz zawiedzie, musisz ponownie wykonać całą rozmowę
  2. kod po stronie serwera będzie prostszy: ponownie modułowość , co oznacza, że ​​różni programiści mogą pracować na różnych zasobach API
  3. W typowym wzorze MVC nie ma sensu, aby jedno wywołanie API ładowało wiele osobnych zasobów ; na przykład, jeśli /productspoprosisz o listę produktów do wyświetlenia na stronie, a także chcesz wyświetlić listę lokalizacji, w których popularne produkty są sprzedawane, masz dwa osobne zasoby: Producti Location. Chociaż są one wyświetlane na tej samej stronie, nie można logicznie zadzwonić pod numer, /productsa także zwrócić lokalizacje
  4. Twoje raporty rejestrowania / wykorzystania będą prostsze w podejściu modułowym. Jeśli poprosisz o to /productsi ładujesz lokalizacje, twoje pliki dziennika będą naprawdę mylące
  5. jeśli masz problem z konkretnym zasobem, podejście z jednym wywołaniem spowoduje uszkodzenie całej strony i nie będzie dla użytkowników oczywiste, co się zepsuło - a to oznacza, że ​​naprawienie problemu potrwa dłużej; jednak w podejściu modułowym, jeśli jedna rzecz się zepsuje, będzie bardzo oczywiste, co się zepsuło i można to naprawić szybciej. Nie zniszczy też reszty strony (chyba że rzeczy są zbyt ściśle powiązane ...)
  6. łatwiej będzie wprowadzić ogólne zmiany, jeśli rzeczy zostaną rozdzielone; jeśli masz jedno ładowanie 5 zasobów przez jedno wywołanie API, trudniej będzie dowiedzieć się, jak nie zepsuć rzeczy, gdy chcesz coś zmienić

Chodzi o to, że zasoby są oddzielne, a w interfejsie API REST zwracanie wielu oddzielnych zasobów z jednej ścieżki API nie ma sensu, nawet jeśli „zapisujesz połączenia z serwerem”. Nawiasem mówiąc, używanie parametrów do warunkowego ładowania (różnych) zasobów nie jest RESTful.

To powiedziawszy, jedyną logiczną opcją jest wykonanie wielu żądań asynchronicznych w celu oddzielenia zasobów: zastosuj podejście modułowe !

PS - Nie należy przedwcześnie optymalizować „połączeń z serwerem”, szczególnie gdy połączenia HTTP są niezwykle niskie narzutem i jesteś w sieci LAN. Tego rodzaju myślenie zamiast wybierania prostszego projektu od samego początku sprawi, że będziesz miał kłopoty później.

Chris Cirefice
źródło
1
Ponadto modułowy jest prawdopodobnie łatwiejszy do testowania jednostkowego.
user949300,
@ user949300 Dobra uwaga, nawet o tym nie myślałem! Testowanie jednostkowe byłoby w rzeczywistości o wiele łatwiejsze, gdyby sprawy zostały rozdzielone.
Chris Cirefice,
Dzięki za szybką i rozszerzoną odpowiedź. Zgadzam się ze wszystkimi, ale myślę, że nie wyjaśniłem tego OK. Będą różne zasoby / Produkt / Lokalizacje itp. Te zasoby można pobrać osobno, ale będzie też inny abstrakcyjny zasób / ekran? Produkt i Lokalizacje, które pobiorą oba w jednym połączeniu. W każdym razie wolę też prostszy sposób.
mattinsalto
@mattinsalto Podejście /screen?Product&Locationsjest złe , przynajmniej z całym moim doświadczeniem w tworzeniu interfejsów API REST i aplikacji internetowej, która ich używała. Z czysto monolitycznego punktu widzenia (np. W Ruby on Rails) posiadanie drogi do /screentego, która ładuje oba zasoby Producti Locationzasoby, jest całkowicie w porządku. Jednak z perspektywy REST nigdy nie będziesz chciał, aby trasa ładowała więcej niż jedną (chyba że jesteś JOINING tabelami, aby uzyskać więcej danych naraz). Co /screennależy zrobić, to załadować podstawowy układ strony i Ajax swoje API, aby uzyskać dane ( Product, Locationitp).
Chris Cirefice,
@mattinsalto Jeśli opracowujesz interfejs API REST do użycia w aplikacji internetowej (a także innych rzeczach), musisz skoncentrować się na danych , a mniej na tym, jak Twoje aplikacje będą je wykorzystywać. Interfejs API REST powinien obsługiwać podstawowe operacje (w razie potrzeby) dla każdego zasobu. Następnie twoja aplikacja internetowa załaduje wszystkie zasoby potrzebne dla danej strony (np. /screenAJAX HTTP GETdo /products/populari /locations). Twój interfejs API nie powinien być tym, który wykonuje wiele ładowań, ponieważ jest mało prawdopodobne, aby dane były wyświetlane w ten sam sposób w aplikacji internetowej na przykład na Androidzie.
Chris Cirefice,