Mandantenfähiges Microservice-Design

13

Wir sind dabei, eine monolithische Anwendung auf eine Microservice-Architektur zu migrieren. Aufgrund einiger regulatorischer Anforderungen müssen wir Kundendaten aus verschiedenen Ländern in separaten (länderspezifischen) Datenbanken speichern. Dh US db für US Kunden, UK db für UK Kunden ...

Die folgenden Designs, die wir in Betracht ziehen, sind wie folgt:

Option 1: Eine mandantenfähige Anwendung mit Unterstützung für mehrere Mandanten im Ruhezustand, die je nach Bedarf auf N-mal skaliert werden kann (denken Sie an Kubernetes-Pods). Eine einzelne Instanz dieser Anwendung kann eine Verbindung zu allen Datenbanken herstellen.

Option 2: Stellen Sie 1 Microservice-Instanz pro Länderdatenbank bereit. Mit einem API-Gateway vor ihnen wird der Datenverkehr weitergeleitet

Wenn Sie diese Art von System entwerfen würden, welche würden Sie wählen?

Hallo Welt
quelle
3
Ich denke, es wird davon abhängen, welche spezifischen funktionalen und nicht funktionalen Anforderungen Sie haben.
Robert Harvey
Verschiedene Datenbanken, aber dieselbe Instanz liest sie? Verstößt das nicht auch gegen die gesetzlichen Anforderungen?
Jimmy T.
Option 1 scheint nicht zu sehr auf den Architekturstil von Microservices abgestimmt zu sein.
Laiv
Sie erwähnen Kebernetes, aber es ist nicht klar, ob Sie Container verwenden oder nicht. Wenn Sie dies beispielsweise mit Docker tun, erstellen Sie einfach eine App, die eine Verbindung zu einer Datenbank herstellt. Wenn Sie dann den Container starten und die Verbindungsdetails über Parameter und / oder Konfiguration angeben. Wenn eine Anwendung eine Verbindung zu vielen ähnlichen Datenbanken herstellt, entstehen nur potenzielle Probleme. Es fügt dem Design nichts Gutes hinzu.
JimmyJames

Antworten:

4

Ich denke, Option 2 ist nicht schlecht, wird aber möglicherweise nicht benötigt. Mit Micro Services können Sie die Anforderungen mehrerer Anwendungen erfüllen.

Ein wichtiger Faktor hierbei ist, ob es einen Unterschied zwischen den beiden Schemata gibt und ob es jemals einen geben wird.

Normalerweise halte ich die Verwendung von Schnittstellen für Repositorys für unnötig. In diesem Fall kann sich die Mühe jedoch lohnen. Repository-Fabriken werden für Sie wichtig sein.

Mein Problem mit Option 1 ist, dass es zu spezifisch ist. Sie sollten in der Lage sein, von dem von Ihnen beschriebenen Setup zu zwei separaten Instanzen zu wechseln, die jeweils auf ihre eigene Datenbank verweisen. Die Anwendung sollte sich nicht darum kümmern, woher sie ihre Daten bezieht.

Während sich das Schema für Ihre zwei unterschiedlichen Datenbanken nicht unterscheidet, kann ein Repository problemlos mit beiden umgehen, ohne dass die Anwendung den Unterschied kennt:

public class MyEntityRepository : ISavesMyEntity, IGetsMyEntity
{
    public MyEntityRepository(string connectionString)
    {
       _connectionString = connectionString;
    }
}

public class MyEntitySaverFactory
{
    public ISavesMyEntity GetSaver(User user)
    {
        if (user.IsUK)
            return new MyEntityRepository(Config.Get("UKConnString"));
        if (user.IsUS)
            return new MyEntityRepository(Config.Get("USConnString"));
        throw new NotImplementedException();
    }
}

//USE
ISavesMyEntity saver = factory.GetSaver(currentUser);
saver.Save(myEntityInstance);

Wenn die DB-Schemas jemals zwischen den USA und Großbritannien unterschiedlich werden, teilen Sie die Funktionalität in zwei völlig unterschiedliche Repositorys auf. Dies wäre einfach, da Sie lediglich Ihre Fabrik wechseln müssten.

TheCatWhisperer
quelle
1
Ich verstehe nicht, warum Sie diese Fabrik brauchen. Warum nicht einfach beim Start den Pfad zu den Konfigurationsdetails übergeben? Dazu müssen Sie den Code jedes Mal ändern, wenn Sie eine neue Region / ein neues Land hinzufügen möchten.
JimmyJames
1
Hier geht es nicht um Benutzer in verschiedenen Ländern, sondern um unterschiedliche Datenbanken. Was ist, wenn es unterschiedliche Schemata gibt? Warum sollte die konsumierende Klasse dafür verantwortlich sein, herauszufinden, woher die DB-Verbindungszeichenfolge stammt?
TheCatWhisperer
Ich weiß nicht was du meinst. Nichts im Code sollte dafür verantwortlich sein, herauszufinden, woher die Verbindungszeichenfolge stammt. Es ist die Konfiguration. Ich verstehe nicht, warum dies anders ist als die Verwendung der Konfiguration für QS-Datenbanken im Vergleich zur Produktion. Sie setzen keine if-Anweisungen in den Code ein, oder?
JimmyJames
Dies ist eine Anwendung, die mit zwei Datenbanken kommuniziert.
TheCatWhisperer
Ich denke, Sie verstehen das Problem falsch: "Wir müssen Kundendaten aus verschiedenen Ländern in separaten (länderspezifischen) Datenbanken speichern." Es ist nicht erforderlich, dass eine einzelne Anwendungsinstanz mit zwei Datenbanken kommuniziert. Ich bezweifle, dass es nur zwei DBs sind. Das OP bedeutete wahrscheinlich "zB", als sie "dh"
tippten
0

Ich würde mit der zweiten Option gehen, es gibt weniger Reibung bei der Entwicklung und Bereitstellung.

Dies ermöglicht eine bessere Skalierbarkeit und Verfügbarkeit sowie bessere Bereitstellungsoptionen ohne Ausfallzeiten, da Sie Ihre App auf eine (oder mindestens eine) Instanz pro Region verteilt haben, im Gegensatz zu mindestens einer für die ganze Welt.

Wenn sich die Anforderungen ändern, haben Sie möglicherweise mehr regionenspezifische Geschäftslogik und möglicherweise auch Datenänderungen. Ich würde versuchen, den Code und seine Daten nach Regionen aufzuteilen und zu vermeiden, regionenspezifische Geschäftslogik zu teilen (möglicherweise teilen Sie am Ende einen Kerncode).

Sinn ergeben?

Sean Farmar
quelle