dlaczego ludzie robią API REST zamiast DBAL?

32

W ostatnich dwóch firmach istniałem w REST API, które istnieją w celu przeszukiwania danych za pośrednictwem aplikacji internetowej. to znaczy. zamiast zmuszać aplikację internetową do wykonywania SQL bezpośrednio, wywołuje interfejs API REST, który robi SQL i zwraca wynik.

Moje pytanie brzmi ... dlaczego to się dzieje?

Jeśli miałby być narażony na działanie stron trzecich, mógłbym to zrozumieć. Lepiej udostępnić ograniczony interfejs API REST niż pełny DB. Ale w obu tych firmach tak nie jest.

Zasugerowano mi, że te API REST ułatwiają przełączanie między DBMS. Ale czy nie o to chodzi w warstwie abstrakcji bazy danych (DBAL)? Być może używasz ORM jako DBAL, a może po prostu piszesz surowy SQL i jeśli to konieczne, DBAL przetłumaczy specyficzne dla DB elementy (np. Przetłumacz LIMIT dla MySQL na TOP dla MSSQL).

Tak czy inaczej wydaje mi się to niepotrzebne. I myślę, że utrudnia to także diagnozowanie problemów. Jeśli raport w aplikacji internetowej podaje nieprawidłowe liczby, nie możesz po prostu zrzucić zapytania SQL - musisz zrzucić URL REST, a następnie przejść do projektu, który służy jako interfejs API REST i wyciągnąć z niego SQL. Jest to więc dodatkowa warstwa pośrednia, która spowalnia proces diagnostyczny.

neubert
źródło
3
Wygląda na to, że pracujesz tylko z aplikacjami, które są w zasadzie CRUD - niektórzy użytkownicy wprowadzają dane za pomocą formularzy, a inni czytają dane za pomocą tych samych formularzy lub za pomocą wydruków raportów? Jeśli nigdy nie pracowałeś z systemem, który potrzebuje złożonego i wyrafinowanego modelu domeny, to mogę zobaczyć, jak byś miał ten szczególny sposób myślenia. Wiele aplikacji wymaga dodatkowej warstwy pośredniej do robienia rzeczy.
RibaldEddie
1
Pracowałem z API (niekoniecznie REST), które (między innymi) wykonywały obliczenia na parametrach, które zostały do ​​niego przekazane. Być może DBMS jest wykorzystywany w tych obliczeniach, ale prawdopodobnie duża część logiki nie istnieje w DB. Jednak wewnętrzne interfejsy API w firmach, w których pracowałem, tego nie robią. Po prostu odpytują DBMS i wypluwają dosłownie wyniki zapytania SQL. Wydaje mi się po prostu, że API REST są często (nie zawsze - często) pisane tak, aby były modne - a nie praktyczne.
neubert
1
Istnieją pewne dziwactwa w projektowaniu interfejsu API REST, które utrudniają dobrze zaprojektowanie złożonej domeny - większość programistów, których poznałem przez lata, nie dba o projekt. Chcą jak najszybciej wydobyć kod, aby ich szefowie pokochali ich i pomyśleli, że są gwiazdami rocka. Łącząc ten fakt z trendem takim jak REST, otrzymujesz modny, ale niepraktyczny API spaghetti. Nie ma to nic wspólnego z samym REST.
RibaldEddie
3
Czy zastanawiałeś się kiedyś, w jaki sposób niektóre firmy internetowe informują, że hakerzy skradzili wszystkie dane użytkowników? Czy zastanawiałeś się kiedyś, jak to zrobił haker? Kiedy myślisz, że serwer sieciowy ma bezpośrednie połączenie z bazą danych, zdajesz sobie sprawę, że po zhakowaniu serwera sieciowego atakujący ma pełny i nieograniczony dostęp do wybierania dowolnych elementów z bazy danych, którą lubi. Trzymaj go za środkowym poziomem, a atakujący będzie mógł wywoływać metody tylko na środkowym poziomie. Nie powiem, że to natychmiastowe bezpieczeństwo, ale znacznie lepsze.
gbjbaanb
1
@gbjbaanb: Chodzi mi o to, że serwer WWW może uzyskać dostęp do danych za pośrednictwem serwera reszty, więc jeśli serwer zostanie zaatakowany przez hakera, osoba atakująca może również uzyskać dostęp do danych za pośrednictwem serwera reszty bez konieczności hakowania serwera reszty.
JacquesB

Odpowiedzi:

28

Jeśli zezwolisz klientowi na bezpośredni dostęp do bazy danych - co by zrobił, nawet z warstwą abstrakcji bazy danych, to:

  • Otrzymujesz sprzężenie między ich kodem a twoim - szczególnie istnieje bardzo silne sprzężenie między strukturą bazy danych a ich kodem;
  • Twój klient może robić w bazie danych dość niepożądane rzeczy - czy to aktualizowanie danych, których nie powinien, pisanie zapytania, które zajmuje zbyt dużo czasu, zakleszczanie czegoś, ponieważ nie uzyskują czystych blokad ...
  • Jeśli dokonałeś mniej niż optymalnego wyboru w strukturze bazy danych, odejście od tego wyboru może być bardzo trudne, szczególnie jeśli nie masz dobrego sposobu na zmigrowanie klientów do nowych struktur.

Oznacza to, że w ogóle nie dotykam części REST - izolowanie bazy danych za interfejsem API jest po prostu bardziej rozsądnym wyborem, jeśli zespół, który utrzymuje bazę danych, i zespoły, które z niej korzystają, nie są zsynchronizowane, ponieważ pozwala tym częściom ewoluują we własnym tempie.

jhominal
źródło
24

Masz rację, nie ma wyraźnej korzyści z wprowadzenia warstwy interfejsu API REST między aplikacją internetową a bazą danych, a to wiąże się z kosztami złożoności i wydajności.

Powodem, dla którego otrzymujesz sprzeczne odpowiedzi, jest zamieszanie dotyczące tego, kim jest „klient” w Twojej architekturze.

W twojej architekturze (o ile dobrze to rozumiem) masz przeglądarki współpracujące z jedną aplikacją internetową, która z kolei wchodzi w interakcję z bazą danych. Wprowadzenie warstwy interfejsu API REST między aplikacją internetową a bazą danych nie przynosi żadnych korzyści. Wszystkie wymienione korzyści (buforowanie, izolacja bazy danych itp.) Można uzyskać dzięki warstwom dostępu do danych w kodzie.

Ale istnieją inne architektury, w których interfejs API REST ma sens:

  • Jeśli masz wielu klientów uzyskujących dostęp do bazy danych - to znaczy nie jedną aplikację internetową, ale wiele niezależnych aplikacji internetowych uzyskujących dostęp do tej samej bazy danych. Korzystne może być utworzenie wspólnego interfejsu REST, aby umożliwić współużytkowanie modelu danych, buforowanie itp. Pewnie możesz czerpać korzyści z udostępniania tych samych bibliotek DAL, ale to nie zadziała, jeśli aplikacje będą tworzone w różnych językach i w różnych językach platformy. Jest to powszechne w systemach korporacyjnych.

  • Jeśli masz wiele aplikacji komputerowych uzyskujących bezpośredni dostęp do bazy danych. Jest to klasyczna architektura „dwupoziomowa”, która wypadła z łask w porównaniu z aplikacjami internetowymi. Wprowadzenie warstwy REST pozwala scentralizować logikę dostępu do danych, a zwłaszcza umożliwia ściślejszą kontrolę bezpieczeństwa, ponieważ ryzykowne jest posiadanie wielu rozproszonych klientów mających bezpośredni dostęp do tej samej bazy danych.

  • Jeśli masz kod JavaScript, który bezpośrednio pobiera dane z serwera, w każdym razie potrzebujesz czegoś takiego jak interfejs API REST.

JacquesB
źródło
1
Podobała mi się twoja odpowiedź, ale mam jeszcze kilka pytań z nią związanych. A co z utratą wydajności po wprowadzeniu kolejnej warstwy abstrakcji? Ponadto, czy nie sprawia, że ​​jest to pojedynczy punkt awarii (jeśli to się skończy, wszystko inne ulegnie awarii) i możliwe wąskie gardło (każda aplikacja czeka na połączenie DB z puli)?
sactiw
@satich: Nie rozumiem dokładnie, o co pytasz, czy możesz być bardziej szczegółowy? Czy pytasz o pojedynczy punkt awarii z warstwą REST lub bez niej?
JacquesB,
Dodatkowa warstwa może się przydać, jeśli komunikuje się z nią więcej niż jedna aplikacja
Ewan
@Ewan: Tak, to stwierdzam w pierwszym punkcie.
JacquesB,
1
@JacquesB Załóżmy, że wiele aplikacji internetowych współużytkuje ten sam DB, ale nie te same dane, tj. Każda wykonuje operacje CRUD na osobnym zestawie danych w tym DB, w zasadzie nie ma udostępniania danych w prawdziwym sensie. Czy więc umieszczanie aplikacji za strukturą trwałego zatrzymywania ma jakiś sens (zakładając również, że DB zapewnia dobry poziom współbieżności w zapytaniach)? Co więcej, czy ten framework nie będzie wąskim gardłem, a także pojedynczym punktem awarii dla tak wielu aplikacji internetowych, które będą przez niego oddziaływać?
sactiw
12

Ostrzeżenie: duży post, kilka opinii, niejasne stwierdzenie „zrób to, co dla ciebie najlepsze”

Zasadniczo odbywa się to jako sposób implementacji „architektury heksagonalnej” wokół bazy danych. Możesz mieć aplikacje internetowe, aplikacje mobilne, aplikacje komputerowe, importery zbiorcze i przetwarzanie w tle, które zużywają bazę danych w jednolity sposób. Z pewnością można to osiągnąć w pewnym stopniu, pisząc bogatą bibliotekę do uzyskiwania dostępu do bazy danych i umożliwiając wszystkim procesom korzystanie z tej biblioteki. I rzeczywiście, jeśli jesteś w małym sklepie z bardzo prostym systemem, jest to prawdopodobnie lepsza droga; To prostsze podejście i jeśli nie potrzebujesz zaawansowanych możliwości bardziej skomplikowanego systemu, po co płacić za złożoność? Jeśli jednak pracujesz z dużym, wyrafinowanym zestawem systemów, z których wszystkie muszą współdziałać z bazą danych na dużą skalę, istnieje „

Niezależność i utrzymanie platformy

Jeśli masz bazę danych i piszesz bibliotekę Python do interakcji z tą bazą danych, a wszyscy wciąga tę bibliotekę do interakcji z bazą danych, to świetnie. Ale powiedzmy nagle, że musisz napisać aplikację mobilną, a ta aplikacja mobilna musi teraz również rozmawiać z bazą danych. I twoi inżynierowie iOS nie używają Pythona, a twoi inżynierowie Androida nie używają Pythona. Może faceci z iOS chcą używać języków Apple, a inżynierowie Androida chcą używać Java. Wtedy utkniesz w pisaniu i utrzymywaniu biblioteki dostępu do danych w 3 różnych językach. Być może twórcy iOS i Androida zdecydują się użyć czegoś takiego jak Xamarin, aby zmaksymalizować kod, który mogą udostępniać. Idealnie, ale prawdopodobnie nadal będziesz musiał przenieść bibliotekę dostępu do danych do .NET. A potem twoja firma właśnie kupiła inną firmę, która „ Aplikacja internetowa to odmienny, ale powiązany produkt, a firma chce zintegrować niektóre dane z platformy firmy z nowo nabytą platformą spółki zależnej. Jest tylko jeden problem: spółka zależna była start-upem i zdecydowała się napisać większość swoich aplikacji w Dart. Dodatkowo, z jakichkolwiek powodów (prawdopodobnie niezależnych od ciebie) zespół mobilny, który pilotował Xamarin, zdecydował, że to nie dla nich, i że wolą używać narzędzi i języków specyficznych dla urządzeń mobilnych, dla których będą opracowywać. Ale kiedy byłeś w tej fazie, twój zespół dostarczył już dużą część twojej biblioteki dostępu do danych w .NET, a inny zespół w firmie pisał jakieś zwariowane rzeczy związane z integracją Salesforce i postanowił zrobić to wszystko w .NET była już biblioteką dostępu do danych dla.

Tak więc teraz, ze względu na bardzo realistyczny obrót wydarzeń, masz bibliotekę dostępu do danych napisaną w Python, .NET, Swift, Java i Dart. Nie są też tak mili, jak byś chciał. Nie można używać ORM tak skutecznie, jak chcesz, ponieważ każdy język ma inne narzędzia ORM, więc musiałeś napisać więcej kodu, niż byś chciał. I nie byłeś w stanie poświęcić tyle czasu na każdą inkarnację, jakiej byś chciał, ponieważ jest ich 5. A wersja biblioteki Dart jest wyjątkowo owłosiona, ponieważ trzeba było stworzyć własne transakcje, ponieważ bibliotek i wsparcia po prostu tak naprawdę nie było. Próbujesz uzasadnić, że z tego powodu aplikacja Dart powinna mieć tylko bazę danych do odczytu, ale firma już zdecydowała, że ​​wszelkie funkcje, które planują, są warte dodatkowego wysiłku. I okazuje się, że istnieje błąd w logice sprawdzania poprawności, który istnieje we wszystkich tych wcieleniach biblioteki dostępu do danych. Teraz musisz napisać testy i kod, aby naprawić ten błąd we wszystkich tych bibliotekach, uzyskać recenzje kodu dotyczące zmian we wszystkich tych bibliotekach, uzyskać kontrolę jakości we wszystkich tych bibliotekach i opublikować zmiany we wszystkich systemach za pomocą wszystkich te biblioteki. W międzyczasie Twoi klienci są niezadowoleni i przeniosą się na Twitter, łącząc wulgaryzmy, których nigdy byś sobie nie wyobrażał. A właściciel produktu decyduje się wcale nie rozumieć sytuacji.

Proszę zrozumieć, że w niektórych środowiskach powyższy przykład nie jest wymyślony. Weź również pod uwagę, że ta sekwencja wydarzeń może się rozwijać w ciągu kilku lat. Ogólnie rzecz biorąc, kiedy dochodzisz do punktu, w którym architekci i ludzie biznesu zaczynają mówić o podłączeniu innych systemów do bazy danych, wtedy chcesz zamienić „umieszczenie interfejsu API REST przed bazą danych” na swoją mapę drogową. Zastanów się, czy na początku, kiedy stało się jasne, że ta baza danych zacznie być współużytkowana przez kilka systemów, przed nią została umieszczona usługa sieci Web / interfejs API REST. Naprawienie błędu sprawdzania poprawności byłoby znacznie szybsze i łatwiejsze, ponieważ robisz to raz zamiast 5 razy. Wydanie poprawki byłoby znacznie łatwiejsze do koordynowania, ponieważ „

TLDR; Łatwiej jest scentralizować logikę dostępu do danych i utrzymywać bardzo cienkich klientów HTTP niż dystrybuować logikę dostępu do danych do każdej aplikacji, która musi uzyskać dostęp do danych. W rzeczywistości Twój klient HTTP może nawet zostać wygenerowany z metadanych. W dużych systemach interfejs API REST pozwala zachować mniej kodu

Wydajność i skalowalność

Niektóre osoby mogą sądzić, że rozmowa z bazą danych zamiast przejścia przez usługę internetową jest szybsza. Jeśli masz tylko jedną aplikację, to z pewnością prawda. Ale w większych systemach nie zgadzam się z sentymentem. Ostatecznie, na pewnym poziomie skali, bardzo korzystne będzie umieszczenie pewnego rodzaju pamięci podręcznej przed bazą danych. Być może używasz Hibernacji i chcesz zainstalować siatkę Infinispan jako pamięć podręczną L2. Jeśli masz klaster 4 rozbudowanych serwerów do obsługi Twojej usługi sieciowej niezależnie od aplikacji, możesz sobie pozwolić na wbudowaną topologię z włączoną replikacją synchroniczną. Jeśli spróbujesz umieścić to w klastrze 30 serwerów aplikacji, narzut związany z włączeniem replikacji w tej konfiguracji będzie zbyt duży, więc „ Będę musiał uruchomić Infinispan w trybie rozproszonym lub w jakiejś specjalnej topologii i nagle Hibernacja musi wyjść z sieci, aby odczytać z pamięci podręcznej. Ponadto Infinispan działa tylko w Javie. Jeśli masz inne języki, będziesz potrzebować innych rozwiązań buforowania. Narzut związany z koniecznością przejścia z aplikacji do usługi internetowej przed dotarciem do bazy danych jest szybko równoważony przez potrzebę korzystania ze znacznie bardziej skomplikowanych rozwiązań buforowania, które generalnie mają własny narzut.

Ponadto ta warstwa HTTP interfejsu API REST zapewnia kolejny cenny mechanizm buforowania. Twoje serwery interfejsu API REST mogą umieszczać nagłówki buforowania w swoich odpowiedziach, a odpowiedzi te mogą być buforowane w warstwie sieci, która skaluje się wyjątkowo dobrze. W małej konfiguracji, z jednym lub dwoma serwerami, najlepszym rozwiązaniem jest po prostu użycie pamięci podręcznej w aplikacji podczas rozmowy z bazą danych, ale na dużej platformie z wieloma aplikacjami działającymi na wielu serwerach chcesz wykorzystać sieć do obsługi twojego buforowania, ponieważ przy odpowiednio skonfigurowanym czymś takim jak kałamarnica, lakier lub nginx można skalować do niesamowitych poziomów na stosunkowo małym sprzęcie. Setki tysięcy lub milionów żądań na sekundę jest o wiele tańsze w przypadku bufora HTTP niż serwera aplikacji lub bazy danych.

Co więcej, posiadanie mnóstwa klientów wskazujących na bazę danych, zamiast skierowania ich wszystkich na kilka serwerów, które z kolei wskazują na bazę danych, może znacznie utrudnić dostrojenie bazy danych i połączeń. Ogólnie rzecz biorąc, większość faktycznego obciążenia na serwerze aplikacji to aplikacje; oczekiwanie na powrót danych z bazy danych jest często czasochłonne, ale generalnie niezbyt drogie obliczeniowo. Być może potrzebujesz 40 serwerów do obsługi obciążenia aplikacji, ale prawdopodobnie nie potrzebujesz 40 serwerów do organizowania pobierania danych z bazy danych. Jeśli poświęcisz to zadanie usłudze sieciowej, prawdopodobnie będzie ona działać na znacznie mniejszej liczbie serwerów niż reszta aplikacji, co oznacza, że ​​będziesz potrzebował znacznie mniej połączeń z bazą danych. Co jest ważne, ponieważ bazy danych na ogół nie

TLDR; Łatwiej jest dostroić, skalować i buforować dostęp do danych, gdy dzieje się to w obrębie jednej dedykowanej usługi internetowej, niż gdy dzieje się tak w wielu różnych aplikacjach korzystających z różnych języków i technologii

Końcowe przemyślenia

Proszę, nie odchodź od myślenia: „Och, zawsze powinienem używać interfejsów API REST, aby uzyskać moje dane” lub „Ten idiota próbuje powiedzieć, że robimy to źle, ponieważ nasza aplikacja internetowa komunikuje się bezpośrednio z bazą danych, ale nasze rzeczy działają dobrze! ” . Najważniejsze jest to, że różne systemy i różne firmy mają różne wymagania; W wielu przypadkach umieszczenie interfejsu API REST przed bazą danych naprawdę nie ma sensu. Jest to bardziej skomplikowana architektura, która wymaga uzasadnienia tej złożoności. Ale gdy złożoność jest uzasadniona, istnieje wiele korzyści z posiadania interfejsu API REST. Umiejętność rozważenia różnych problemów i wybrania odpowiedniego podejścia do systemu jest tym, co czyni dobrego inżyniera.

Ponadto, jeśli interfejs API REST przeszkadza w debugowaniu, prawdopodobnie na tym obrazie brakuje czegoś lub jest on nieprawidłowy. Nie sądzę, że dodanie tej warstwy abstrakcji samo w sobie utrudnia debugowanie. Kiedy pracuję z dużymi, n-poziomowymi systemami, lubię mieć pewność, że mam rozproszony kontekst rejestrowania. Być może, gdy użytkownik zainicjuje żądanie, wygeneruj identyfikator GUID dla tego żądania i zaloguj nazwę użytkownika tego użytkownika oraz zgłoszone przez niego żądanie. Następnie przekaż ten identyfikator GUID, gdy aplikacja komunikuje się z innymi systemami. Dzięki odpowiedniej agregacji i indeksowaniu dzienników możesz zapytać całą platformę o użytkownika zgłaszającego problem, mieć wgląd we wszystkie swoje działania, a oni przeciekają przez system, aby szybko zidentyfikować, co się stało. Znowu jest to bardziej skomplikowana architektura,

Źródła: http://alistair.cockburn.us/Hexagonal+architecture https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing

Psy
źródło
Bardzo dobra odpowiedź, warta przeczytania. Dziękujemy za poświęcenie czasu na napisanie tej wspaniałej odpowiedzi!
Dominic
6

Jeśli dobrze rozumiem, czym jest DBAL , odpowiedź brzmi: interfejs REST pozwala używać dowolnego języka dla jego klientów, podczas gdy DBAL jest biblioteką, która pozwala używać jednego języka dla jego klientów.

To z kolei może być zaletą dla firmy, w której jest wiele zespołów programistycznych i nie wszystkie są biegłe w tym samym języku. Zezwolenie oprogramowaniu na bezpośrednie zapytania do bazy danych byłoby równoważne pod względem funkcjonalności, ale jak mówisz „lepiej ujawnić ograniczony interfejs API REST niż pełną bazę danych”.

Mówiąc bardziej abstrakcyjnie, sam odpowiadasz na pytanie:

Jest to więc dodatkowa warstwa pośrednia, która spowalnia proces diagnostyczny

... ponieważ istnieje ten słynny aforyzm, który stwierdza: „Wszystkie problemy w informatyce można rozwiązać przez inny poziom pośredni”. :)

logc
źródło
6

To, że jesteś w tej samej firmie, nie oznacza, że ​​powinieneś ujawniać wszystko wszystkim. Interfejsy API REST to sposób na zdefiniowanie ograniczonych relacji konsument / dostawca między zespołami w firmie, z wyraźną umową. Amazon jest pionierem w tej formie organizacji.

Interfejsy API zapewniają również warstwę abstrakcji, umożliwiając korzystanie z określonego zestawu idiomów - niekoniecznie chcesz rozmawiać z konsumentami na takich samych zasadach, jak w bazie danych. Również niekoniecznie chcesz rozmawiać z każdym konsumentem w ten sam sposób.

guillaume31
źródło
3

Myślisz, że REST służy do zapytań do bazy danych i tak nie jest. REST reprezentuje stan czegoś w tej chwili. Użycie REST zmienia lub pobiera reprezentację, ale to wszystko. Jeśli stan ten stanie się dostępny dla bazy danych, nie ma to znaczenia i nikogo to nie obchodzi, ponieważ JAK powstaje reprezentacja, nie jest częścią REST, ani zapytania do bazy danych.

Obrabować
źródło
Nie sugeruję, że zapytania do bazy danych == REST. Z pewnością REST może być czymś więcej niż warstwą abstrakcji bazy danych, ale w przeszłości dwie firmy, nad którymi pracowałem, są zasadniczo wszystkim, czym jest - warstwą abstrakcji bazy danych. To nie robi nic innego , niż tłumaczyć żądania HTTP do zapytań DB. A jeśli to wszystko, co robisz, wydaje mi się, że DBAL lepiej Ci służy. Rzeczywiście wydaje mi się, że jedynym powodem, dla którego niektórzy używają REST, jest to, że jest modny - a nie dlatego, że jest to najlepsze rozwiązanie dla danego zadania.
neubert
@neubert czy DBAL działa bezpośrednio przez Internet, podobnie jak REST?
Rob
Pewnie. Możesz powiedzieć MySQL, aby używał adresu IP / nazwy domeny / portu, który należy do innego komputera w Internecie. Możesz korzystać z tunelowania SSH, a także (wierzę) uwierzytelniania SSL. Przypuszczalnie inne DBMS działają podobnie.
neubert
@neubert: w takim przypadku interfejs API REST jest DBAL, prawda?
RemcoGerlich,
2
@RemcoGerlich - jasne, ale używanie REST API jako DBAL może dodawać środkową warstwę, która jest niepotrzebna i utrudnia diagnozę problemów. Mam na myśli, że jeśli użyjesz wystarczająco szerokiej definicji DBAL, możesz uznać Google SERP za DBAL. Musisz tylko przeanalizować HTML, aby uzyskać paginowane dane z serwerów Google ...
neubert