Aufgrund einer Kombination aus Geschäfts- / Unternehmensanforderungen und den Vorlieben unseres Architekten sind wir zu einer bestimmten Architektur gekommen, die mir ein wenig abgeneigt erscheint, aber ich habe nur sehr begrenzte Architekturkenntnisse und noch weniger Cloud-Kenntnisse, daher würde ich gerne einen Sanity Check sehen Wenn hier Verbesserungen vorgenommen werden können:
Hintergrund: Wir entwickeln einen Ersatz für ein bestehendes System, das von Grund auf neu geschrieben wurde. Dies erfordert, dass wir Daten von einer SAP-Instanz über BAPI / SOAP-Webdienste beziehen und einige eigene Datenbanken für Daten verwenden, die nicht in SAP enthalten sind. Derzeit sind alle Daten, die wir verwalten werden, in lokalen DBs in einer verteilten Anwendung oder in einer MySQL-Datenbank vorhanden, aus der migriert werden muss. Wir müssen eine Handvoll Webanwendungen erstellen, die die Funktionalität der vorhandenen verteilten App replizieren und administrative Funktionen für die von uns kontrollierten Daten bereitstellen.
Geschäfts- / Unternehmensanforderungen:
Alle von uns kontrollierten Datenbanken müssen in MS SQL Server implementiert sein
Minimieren Sie die Anzahl der erstellten Datenbanken
In Phase 1 werden wir unsere Anwendungen in Azure bereitstellen, aber wir müssen in der Lage sein, diese Anwendungen in Zukunft vor Ort bereitzustellen
Unser Ops-Team möchte, dass wir alles andocken, da sie der Meinung sind, dass dies die Verwaltung des Codes erheblich vereinfacht.
Replikation von Daten minimieren / eliminieren
Der Codierungsstapel wird .NET Core für Microservices und Admin-Apps sein, Angular 5 jedoch für die Haupt-Front-End-Anwendung.
Aus diesen Anforderungen entwickelte unser Architekt diesen Entwurf:
Unsere Frontends werden von einer Reihe von Microservices gespeist (ich verwende diesen Begriff leichtfertig, da sie auf Domain-Ebene und ziemlich groß sind), die in jeder Domain in Lese- und Schreibdienste unterteilt werden. Beide sind über Kubernetes skalierbar und lastausgeglichen. Jeder hat auch eine schreibgeschützte Kopie seiner Datenbank in seinem Container angehängt, wobei eine einzelne Master-Instanz der Datenbank für Schreibvorgänge verfügbar ist, die Aktualisierungen dieser schreibgeschützten Kopien herausbringt.
(Entschuldigung für die schlechte Bildqualität, ich mache sie aus dem Speicher wieder gut, da es natürlich keine eigentliche Dokumentation für dieses Zeug gibt, außer im Kopf des Architekten.)
Die Service-to-Service-Kommunikation erfolgt über eine Nachrichtenwarteschlange, die jeder Dienst abhört und alle relevanten Nachrichten verarbeitet. Dies wird hauptsächlich für die E-Mail-Generierung verwendet, da wir noch nichts identifiziert haben, das Service-to-Service-Kommunikation für Informationen erfordert. Alles, was mit "Geschäftslogik" zu tun hat und die Beteiligung mehrerer Dienste erfordern würde, würde wahrscheinlich von den Frontends ausgehen, wo die Frontends jeden Dienst einzeln aufrufen und sich mit Atomizität befassen würden.
Aus meiner Sicht reiben mich die schreibgeschützten Datenbankinstanzen, die sich in den Docker-Containern für die Dienste drehen, in die falsche Richtung. Der Dienst selbst und die Datenbank hätten drastisch unterschiedliche Anforderungen an die Last, daher wäre es viel sinnvoller, wenn wir sie separat ausgleichen könnten. Ich glaube, MYSQL hat eine Möglichkeit, dies mit Master / Slave-Konfigurationen zu tun, bei denen neue Slaves hochgefahren werden können, wenn die Last hoch wird. Insbesondere wenn wir unser System in der Cloud haben und für jede Instanz bezahlen, erscheint es verschwenderisch, eine neue Instanz des gesamten Dienstes zu starten, wenn wir nur eine andere Datenbankinstanz benötigen (wie im Gegenteil, eine neue Datenbankkopie zu starten, wenn wir es wirklich gerade tun benötigen eine Webdienstinstanz). Ich kenne jedoch die Einschränkungen von MS SQL Server dafür nicht.
Mein größtes Anliegen ist die Implementierung von MS SQL Server. Es fühlt sich falsch an, die schreibgeschützten Instanzen so eng mit den Diensten zu koppeln. Gibt es einen besseren Weg, dies zu tun?
HINWEIS: Ich habe dies beim Software-Engineering angefragt und sie haben mich hier gezeigt. Entschuldigung, wenn dies nicht die entsprechende SE ist.
Es gibt auch kein MS SQL Server-Tag
quelle
Antworten:
Im Wesentlichen haben Sie ein Caching-System entworfen. Die Service-Container verfügen vermutlich über eine lokale Kopie der Daten, sodass sie für Lesevorgänge keine zusätzliche Netzwerkreise durchführen müssen.
Wie Sie bereits betont haben, besteht ein Standardansatz darin, einen Cluster von Lesereplikaten zu haben, aus denen alle Container lesen können. Auf diese Weise können Sie sie getrennt von den Anwendungsservern skalieren, was gut ist, da sie im Allgemeinen unterschiedliche Dinge benötigen (möchten Sie wirklich jedem Anwendungscontainer große Mengen an RAM zuweisen?). Dadurch werden Netzwerkaufrufe für Datenbanklesevorgänge hinzugefügt, aber bis sich herausstellt, dass dies ein Problem ist, würde ich die Architektur nicht komplizieren, um es zu lösen.
Wenn es tut , zu einem Problem werden, eine viel leichtere Art und Weise das Problem der Handhabung ist eine tatsächliche Cache lokal, wie memcache oder redis laufen. Sie können die TTLs für einzelne Objekte entsprechend anpassen. Es werden automatisch selten angeforderte Daten gelöscht, um den Anwendungsserver hell zu halten.
quelle
Ich könnte viel über die Architektur sprechen, aber dies ist eine Entwickler-Community, daher werde ich auf Ihr Hauptanliegen eingehen, nur die Datenbank auszuführen.
Kurze Antwort:
Wenn Sie das Design so ändern würden, dass für jeden Microservice "Azure SQL" angezeigt wird, würde es für mich in Ordnung aussehen. Jeder Microservice kann über eine eigene Azure SQL-Datenbankinstanz verfügen (die wahrscheinlich auf einem gemeinsam genutzten Cluster ausgeführt wird, für Sie jedoch unsichtbar ist). Um es später vor Ort zu verschieben, können Sie entscheiden, ob Sie ein "Azure SQL-ähnliches" Setup auf Kubernetes erstellen oder einfach einen herkömmlichen SQL Server-Cluster vor Ort ausführen möchten. Durch die Verwendung von Azure SQL wird Ihre Architektur nicht an Azure gebunden, wie im Folgenden erläutert wird.
Lange Antwort:
MS SQL Server benötigt im Vergleich zu Open Source-Datenbanken oder zustandslosen Anwendungsdiensten eine große Menge an Speicher. Es sind auch Softwarelizenzen erforderlich (wir werden uns unten mit der Optimierung der Kosten befassen). Es kann also vorkommen, dass es einfach nicht besonders kostengünstig ist, eine lizenzierte Instanz pro Dienst auszuführen. Sie können eine SQLServer-Instanz lizenzieren und viele private Datenbanken pro Dienst darauf ausführen. Verwenden Sie noch besser Azure SQL, die verwaltete Datenbank-als-Dienst-Version von SQL Server. Dadurch werden sie nicht in Azure gesperrt, da Sie zu AWS mit "Amazon RDS for SQL Server" wechseln können. Jeder seriöse Cloud-Anbieter bietet einen professionell verwalteten Datenbankdienst für alle wichtigen Datenbanken an.
Wenn Sie darauf hinweisen, dass eine Datenbank im selben Kubernetes-Pod wie Ihr Anwendungsservercode ausgeführt wird, können Sie sie nicht unabhängig voneinander skalieren. Statuslose Anwendungsserver können auch auf Pods ausgeführt werden, die keinen dauerhaften Speicher haben. Dann können zustandslose Anwendungsserver sterben und nach Belieben neu gestartet und trivial zwischen Cloud-Verfügbarkeitszonen verschoben werden. Offensichtlich benötigen Datenbanken dauerhaften Speicher, der dem Pod "gehört". Eine Datenbank benötigt also einen dauerhaften Volumenanspruch. Wenn Sie möchten, dass sie mit hoher Verfügbarkeit ausgeführt werden, müssen sie als Stateful Set ausgeführt werden. Das Ausführen der Datenbank im selben Pod wie der Anwendungsserver ist etwas, das ein Entwickler möglicherweise lokal ausführt, aber ich würde es für SQL Server nicht empfehlen, da es 10x langsamer als Ihr Code startet. Führen Sie das SQL Server-Docker-Image auf einem Mac-Laptop aus, um seinen Port freizulegen.
Es wird als sehr standardmäßige Architektur angesehen, da jeder Mikrodienst über eine eigene logische (aber nicht unbedingt physische) Datenbank verfügt, die jedoch als zustandsloser Dienst mit vielen Replikaten ausgeführt werden kann, damit sie unabhängig voneinander skaliert werden können. Außerdem unterstützt Azure Redis als Cache sehr gut. Es wird daher als Standardarchitektur für jeden Mikrodienst angesehen, über eine eigene logische private Datenbank, einen eigenen privaten Redis-Cache und viele unabhängig skalierte Pods zu verfügen. Wenn Sie Azure SQL und Azure Redis mieten, können Sie nicht auswählen, wie sie es physisch ausführen. Und warum willst du? Lassen Sie die Fachleute herausfinden, wie Sie ein robustes Setup mit hoher Leistung ausführen, das Sie "für das bezahlen können, was Sie verwenden", und konzentrieren Sie sich darauf, Ihre Geschäftslogik zu schreiben, und nicht darauf, Stateful Services in der Cloud zu verwalten, die Sie problemlos mieten können.
Ich habe Entwickler gesehen, die MS SQL Server Express lokal auf ihrem Laptop ausführen, um zu debuggen und Unit-Tests durchzuführen und dann in Kubernetes unter Azure bereitzustellen, wo die Microservices-Datenbanken alle unter Azure SQL ausgeführt werden. Ich habe auch Teams gesehen, die in der Produktion gegen Azure SQL ausgeführt wurden, aber gegen das SQL Server-Setup auf einfachen VMs in Azure getestet haben. Warum? Weil Azure SQL nur mit "Produktionspreisen" geliefert wird. Diese Organisation verfügte bereits über SQL Server On-Prem und DBAs, sodass es für sie billiger war, SQL Server auf VMs in Azure zu installieren und auszuführen, um die Test-Envs zu hosten. Alle Microservices hatten ihre eigenen privaten Datenbanken. Testen Sie die Daten pro Mikroservice-Datenbank auf einer gemeinsam genutzten SQL Server-Instanz auf VMs mit einem Cluster mit zwei Knoten, um die Ausfallsicherheit zu gewährleisten. In der Produktion befanden sich die Instanzen pro Microservices alle in Azure SQL für hohe Leistung und hohe Verfügbarkeit.
quelle