Warnung: großer Beitrag, einige Meinungen, vage Schlussfolgerung, was für Sie am besten funktioniert
Im Allgemeinen wird dies als Mittel zum Implementieren einer "hexagonalen Architektur" in Ihrer Datenbank durchgeführt. Sie können dafür sorgen, dass Webanwendungen, mobile Anwendungen, Desktopanwendungen, Massenimporteure und Hintergrundverarbeitung Ihre Datenbank auf einheitliche Weise belegen. Sicherlich können Sie dasselbe in gewissem Maße erreichen, indem Sie eine umfangreiche Bibliothek für den Zugriff auf Ihre Datenbank schreiben und alle Ihre Prozesse diese Bibliothek verwenden lassen. Und in der Tat, wenn Sie in einem kleinen Laden mit einem sehr einfachen System sind, ist dies wahrscheinlich der bessere Weg. Es ist ein einfacherer Ansatz, und wenn Sie nicht die erweiterten Funktionen eines komplizierten Systems benötigen, warum sollten Sie dann für die Komplexität bezahlen? Wenn Sie jedoch mit einer großen, hoch entwickelten Gruppe von Systemen arbeiten, die alle in großem Maßstab mit Ihrer Datenbank interagieren müssen, gibt es
Plattformunabhängigkeit & Wartung
Wenn Sie über eine Datenbank verfügen und eine Python-Bibliothek für die Interaktion mit dieser Datenbank schreiben und jeder diese Bibliothek für die Interaktion mit der Datenbank abruft, ist das großartig. Angenommen, Sie müssen plötzlich eine mobile App schreiben und diese mobile App muss jetzt auch mit der Datenbank kommunizieren. Und Ihre iOS-Ingenieure verwenden kein Python, und Ihre Android-Ingenieure verwenden kein Python. Vielleicht wollen die iOS-Leute Apples Sprachen und die Android-Ingenieure Java verwenden. Dann müssen Sie Ihre Datenzugriffsbibliothek nicht mehr in drei verschiedenen Sprachen schreiben und verwalten. Möglicherweise entscheiden sich iOS- und Android-Entwickler für die Verwendung von Xamarin, um den Code zu maximieren, den sie gemeinsam nutzen können. Perfekt, außer dass Sie Ihre Datenzugriffsbibliothek wahrscheinlich noch nach .NET portieren müssen. Und dann hat Ihre Firma gerade eine andere Firma gekauft, die Die Webanwendung von S ist ein eigenständiges, aber verwandtes Produkt, und das Unternehmen möchte einen Teil der Daten von der Plattform Ihres Unternehmens in die Plattform der neu erworbenen Tochtergesellschaft integrieren. Es gibt nur ein Problem: Die Tochtergesellschaft war ein Start-up und beschloss, den Großteil ihrer Bewerbung in Dart zu schreiben. Außerdem hat das mobile Team, das Xamarin pilotiert hat, aus irgendeinem Grund (wahrscheinlich aus Gründen, auf die Sie keinen Einfluss haben) entschieden, dass es nicht für sie ist und dass sie lieber die Tools und Sprachen verwenden, die für die mobilen Geräte bestimmt sind, für die sie entwickelt werden. In dieser Phase hatte Ihr Team bereits einen großen Teil Ihrer Datenzugriffsbibliothek in .NET bereitgestellt, und ein anderes Team im Unternehmen schrieb verrückte Salesforce-Integrationsaufgaben und beschloss, dies alles seitdem in .NET zu tun war schon eine Datenzugriffsbibliothek für.
Aufgrund einer sehr realistischen Entwicklung haben Sie Ihre Datenzugriffsbibliothek nun in Python, .NET, Swift, Java und Dart geschrieben. Sie sind auch nicht so nett, wie Sie es gerne hätten. Sie konnten ein ORM nicht so effektiv einsetzen, wie Sie es möchten, da jede Sprache andere ORM-Tools hat. Sie mussten also mehr Code schreiben, als Sie möchten. Und Sie waren nicht in der Lage, jeder Inkarnation so viel Zeit zu widmen, wie Sie wollten, weil es 5 davon gibt. Und die Dart-Version der Bibliothek ist besonders haarig, weil Sie für einige davon Ihre eigenen Transaktionssachen rollen mussten, weil die Bibliotheken und der Support einfach nicht wirklich da waren. Sie haben versucht, den Fall zu begründen, dass die Dart-Anwendung aus diesem Grund nur Lesezugriff auf Ihre Datenbank haben sollte. Aber das Unternehmen hatte sich bereits entschieden, dass die von ihnen geplanten Funktionen den zusätzlichen Aufwand wert waren. Und es stellt sich heraus, dass einige der Validierungslogiken in all diesen Inkarnationen Ihrer Datenzugriffsbibliothek fehlerhaft sind. Jetzt müssen Sie Tests und Code schreiben, um diesen Fehler in all diesen Bibliotheken zu beheben, Codeüberprüfungen für Ihre Änderungen an all diesen Bibliotheken abrufen, QS für all diese Bibliotheken abrufen und Ihre Änderungen für alle Systeme freigeben, die alle von verwenden diese Bibliotheken. In der Zwischenzeit sind Ihre Kunden unzufrieden und haben auf Twitter gewechselt. Sie haben Kombinationen von Ungereimtheiten zusammengestellt, von denen Sie nie gedacht hätten, dass sie auf das Flaggschiffprodukt Ihres Unternehmens abzielen. Und der Produktbesitzer entscheidet sich dafür, die Situation überhaupt nicht sehr zu verstehen.
Bitte haben Sie Verständnis dafür, dass das obige Beispiel in einigen Umgebungen alles andere als erfunden ist. Bedenken Sie auch, dass sich diese Abfolge von Ereignissen im Laufe einiger Jahre entwickeln kann. Wenn Architekten und Geschäftsleute anfangen, andere Systeme an Ihre Datenbank anzuschließen, sollten Sie in der Regel eine REST-API vor die Datenbank setzen. Überlegen Sie sich, ob zu einem frühen Zeitpunkt, als klar war, dass diese Datenbank von einigen wenigen Systemen gemeinsam genutzt werden würde, ein Web-Service / eine REST-API davor gestellt wurde. Das Beheben Ihres Überprüfungsfehlers wäre viel schneller und einfacher, da Sie dies nur einmal anstatt fünfmal tun. Und die Veröffentlichung des Fixes wäre viel einfacher zu koordinieren, weil Sie
TLDR; Es ist einfacher, die Datenzugriffslogik zu zentralisieren und sehr dünne HTTP-Clients zu verwalten, als die Datenzugriffslogik an jede Anwendung zu verteilen, die auf die Daten zugreifen muss. Tatsächlich kann Ihr HTTP-Client sogar aus Metadaten generiert werden. In großen Systemen können Sie mit der REST-API weniger Code verwalten
Leistung und Skalierbarkeit
Einige Leute glauben vielleicht, dass es schneller ist, direkt mit der Datenbank zu sprechen, anstatt zuerst einen Webdienst zu durchlaufen. Wenn Sie nur eine Anwendung haben, ist das sicherlich richtig. Aber in größeren Systemen stimme ich dem Gefühl nicht zu. Irgendwann wird es auf einer gewissen Skalierungsebene sehr vorteilhaft sein, eine Art Cache vor die Datenbank zu stellen. Möglicherweise verwenden Sie den Ruhezustand und möchten ein Infinispan-Grid als L2-Cache installieren. Wenn Sie einen Cluster von 4 bulligen Servern haben, um Ihren Webdienst unabhängig von Ihren Anwendungen zu hosten, können Sie es sich leisten, eine eingebettete Topologie mit aktivierter synchroner Replikation zu haben. Wenn Sie versuchen, dies auf einem Cluster von 30 Anwendungsservern unterzubringen, ist der Aufwand für das Aktivieren der Replikation in diesem Setup zu hoch. Entweder muss Infinispan in einem verteilten Modus oder in einer dedizierten Topologie ausgeführt werden, und Hibernate muss plötzlich über das Netzwerk gehen, um aus dem Cache zu lesen. Außerdem funktioniert Infinispan nur in Java. Wenn Sie über andere Sprachen verfügen, benötigen Sie andere Caching-Lösungen. Der Netzwerkaufwand, der anfällt, um die Datenbank zu erreichen, wenn Sie von Ihrer Anwendung zu Ihrem Webdienst wechseln, wird schnell durch die Notwendigkeit kompensiert, komplexere Caching-Lösungen zu verwenden, die in der Regel mit einem eigenen Aufwand verbunden sind.
Darüber hinaus bietet diese HTTP-Ebene Ihrer REST-API einen weiteren nützlichen Caching-Mechanismus. Ihre Server für Ihre REST-API können Caching-Header in ihre Antworten einfügen, und diese Antworten können auf der Netzwerkebene zwischengespeichert werden, die sich außergewöhnlich gut skalieren lässt. In einer kleinen Konfiguration mit einem oder zwei Servern ist es am besten, einen Cache im Speicher in der Anwendung zu verwenden, wenn diese mit der Datenbank kommuniziert. In einer großen Plattform mit vielen Anwendungen, die auf vielen Servern ausgeführt werden, möchten Sie jedoch den Cache nutzen Netzwerk, um Ihr Caching zu handhaben, weil bei richtiger Konfiguration etwas wie Tintenfisch oder Lack oder Nginx auf relativ kleiner Hardware zu wahnsinnigen Ebenen skaliert werden kann. Hunderttausende oder Millionen von Anforderungen pro Sekunde Durchsatz sind in einem HTTP-Cache viel billiger als auf einem Anwendungsserver oder einer Datenbank.
Darüber hinaus können viele Clients auf Ihre Datenbank verweisen, anstatt auf einige Server, die wiederum auf die Datenbank verweisen, was das Optimieren der Datenbank und das Zusammenlegen von Verbindungen erheblich erschwert. Im Allgemeinen handelt es sich bei der tatsächlichen Arbeitslast auf einem Anwendungsserver hauptsächlich um Anwendungssachen. Das Warten auf das Zurückkommen von Daten aus der Datenbank ist oft zeitaufwändig, aber im Allgemeinen nicht sehr rechenintensiv. Sie benötigen möglicherweise 40 Server, um die Arbeitslast Ihrer Anwendung zu bewältigen, aber Sie benötigen wahrscheinlich keine 40 Server, um das Abrufen der Daten aus der Datenbank zu koordinieren. Wenn Sie diese Aufgabe einem Webdienst zuweisen, wird der Webdienst wahrscheinlich auf weitaus weniger Servern als der Rest der Anwendung ausgeführt, sodass Sie weitaus weniger Verbindungen zur Datenbank benötigen. Welches ist wichtig, weil Datenbanken in der Regel don '
TLDR; Es ist einfacher, den Datenzugriff zu optimieren, zu skalieren und zwischenzuspeichern, wenn er in einem einzigen dedizierten Webdienst stattfindet, als wenn er in vielen verschiedenen Anwendungen mit unterschiedlichen Sprachen und Technologien stattfindet
Abschließende Gedanken
Bitte kommen Sie nicht von diesem Gedanken ab "Oh wow, ich sollte immer REST-APIs verwenden, um meine Daten abzurufen " oder "Dieser Idiot versucht zu sagen, dass wir es falsch machen, weil unsere Web-App direkt mit der Datenbank kommuniziert, aber unser Zeug funktioniert gut! " . Der wichtigste Punkt, den ich ansprechen möchte, ist, dass unterschiedliche Systeme und unterschiedliche Unternehmen unterschiedliche Anforderungen haben. In vielen Fällen ist es nicht sinnvoll, eine REST-API vor Ihre Datenbank zu stellen. Es ist eine kompliziertere Architektur, die es erfordert, diese Komplexität zu rechtfertigen. Wenn die Komplexität jedoch gerechtfertigt ist, bietet die Verwendung der REST-API zahlreiche Vorteile. Es ist das, was einen guten Ingenieur auszeichnet, wenn er die unterschiedlichen Bedenken abwägt und den richtigen Ansatz für Ihr System wählt.
Wenn die REST-API das Debuggen von Dingen behindert, ist wahrscheinlich etwas in diesem Bild falsch oder nicht vorhanden. Ich glaube nicht, dass diese zusätzliche Abstraktionsebene das Debuggen wesentlich erschwert. Wenn ich mit großen n-Tier-Systemen arbeite, möchte ich sicherstellen, dass ich über einen verteilten Protokollierungskontext verfüge. Wenn ein Benutzer eine Anforderung initiiert, generieren Sie möglicherweise eine GUID für diese Anforderung und protokollieren Sie den Benutzernamen dieses Benutzers und die Anforderung, die er gestellt hat. Geben Sie diese GUID dann weiter, wenn Ihre Anwendung mit anderen Systemen kommuniziert. Mit einer ordnungsgemäßen Protokollaggregation und -indizierung können Sie die gesamte Plattform nach dem Benutzer abfragen, der das Problem meldet. Außerdem haben Sie Einblick in alle Aktionen und können schnell feststellen, wo Fehler aufgetreten sind. Wieder ist es eine kompliziertere Architektur,
Quellen:
http://alistair.cockburn.us/Hexagonal+architecture
https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing