1

Hinweis: Dies ist eine designbezogene Frage, auf die ich keine befriedigende Antwort finden konnte. Daher hier fragen.Verbindungspooling und Skalierung von Instanzen

Ich habe eine Spring-Boot-App, die in Cloud (Cloud Foundry) eingesetzt wird. Die App stellt eine Verbindung zu einer Oracle-Datenbank her, um Daten abzurufen. Die Anwendung verwendet einen Verbindungspool (HikariCp), um die Verbindungen zur Datenbank aufrechtzuerhalten. Nehmen wir an, die Anzahl der Verbindungen ist auf 5 eingestellt. Jetzt hat die Anwendung die Fähigkeit, automatisch basierend auf der Auslastung zu skalieren. Alle Instanzen teilen dieselbe Datenbank. Zu jedem Zeitpunkt konnten 50 Instanzen der gleichen Anwendung ausgeführt werden, was bedeutet, dass die Gesamtzahl der Datenbankverbindungen 250 (dh 5 * 50) beträgt.

Angenommen, die Datenbank kann nur 100 gleichzeitige Verbindungen verarbeiten. Im aktuellen Szenario verbrauchen 20 Instanzen die 100 verfügbaren Verbindungen. Was passiert, wenn die nächsten 30 Instanzen versuchen, sich mit db zu verbinden? Wenn dies ein Designproblem ist, wie kann dies vermieden werden?

Bitte beachten Sie, dass die Zahlen in der Frage der Einfachheit halber hypothetisch sind. Die tatsächlichen Zahlen sind viel höher.

Antwort

1

Sagen wir:

  • Anzahl der zur Verfügung stehenden DB-Verbindungen = X
  • Anzahl der gleichzeitigen Instanzen Ihrer Anwendung = Y
  • Maximale Größe des DB-Verbindungspool in jeder Instanz Ihrer Anwendung = X/Y

Das ist etwas einfach, da Sie in der Lage sein möchten, eine Verbindung zu Ihrem d atabase von anderen Clients (z. B. Support-Tools), so ist vielleicht eine sicherere Formel (X * 0.95)/Y.

Jetzt haben Sie sichergestellt, dass Ihre Anwendungsebene keine Probleme mit der Verbindung "Keine Datenbankverbindung existiert" hat. Wenn jedoch (X * 0.95)/Y 25 ist und mehr als 25 gleichzeitige Anforderungen Ihre Anwendung durchlaufen, die gleichzeitig eine Datenbankverbindung benötigen, treten bei einigen dieser Anfragen Verzögerungen auf, wenn Sie versuchen, eine Datenbankverbindung zu erwerben, und wenn diese Verzögerungen überschritten werden Ein konfigurierter Timeout führt zu fehlgeschlagenen Anfragen.

Wenn Sie den Durchsatz in Ihrer Anwendung begrenzen können, so dass Sie nie mehr als (X * 0.95)/Y gleichzeitige 'Get-Datenbank-Verbindung' Anfragen dann hey presto das Problem verschwindet. Aber natürlich ist das nicht typisch realistisch (in der Tat, weniger ist selten mehr ... Ihren Kunden zu sagen, dass sie aufhören sollen, mit Ihnen zu reden, ist im Allgemeinen ein komisches Signal, das Sie senden können). Dies bringt uns zum Kern des Problems:

Jetzt hat die Anwendung die Fähigkeit, basierend auf der Last automatisch zu skalieren.

Aufwärtsskalierung ist nicht frei. Wenn Sie die gleiche Reaktionsfähigkeit bei der Behandlung von N gleichzeitige Anfragen haben möchten, wie Sie bei der Behandlung von 100000N gleichzeitige Anfragen haben, dann muss etwas geben; Sie müssen die Ressourcen erhöhen, die diese Anforderungen benötigen. Wenn sie also Datenbankverbindungen verwenden, muss die Anzahl gleichzeitiger Verbindungen, die von Ihrer Datenbank unterstützt werden, steigen. Wenn serverseitige Ressourcen nicht proportional zur Clientauslastung wachsen können, benötigen Sie eine gewisse Art von Gegendruck, oder Sie müssen Ihre serverseitigen Ressourcen sorgfältig verwalten. Eine gängige Methode zur Verwaltung Ihrer serverseitigen Ressourcen besteht darin, ...

  • Ihren Service Stellen nicht blockierende dh delegieren jede Client-Anfrage an einen Threadpool und reagieren auf den Client über Rückrufe in Ihrem Dienst (Frühling erleichtert dies über DeferredResult oder seine Async Rahmen oder seine RX-Integration)
  • Konfigurieren Sie Ihren Server-Seite Ressourcen (wie zB die maximale Anzahl der verfügbaren Verbindungen von Ihrer DB erlaubten) den maximalen Teiledurchlauf von Ihren Dienstleistungen entsprechen bezogen auf der Gesamtgröße Ihrer Service-Instanz der Client-Anfrage threadpools

die Client-Anfrage thread~~POS=TRUNC Grenzen die Anzahl der momentan aktiven Anfragen in jedem s erice Instanz es tut nicht begrenzen Sie die Anzahl der Anfragen, die Ihre Kunden einreichen können. Bei diesem Ansatz kann der Dienst nach oben skaliert werden (bis zu einem Grenzwert, der durch die Größe der Client-Request-Threadpools über alle Serviceinstanzen hinweg repräsentiert wird). Dadurch kann der Serviceinhaber die Schutzressourcen (z. B. ihre Datenbank) vor Überlastung schützen. Und da alle Client-Anfragen akzeptiert werden (und an den Client-Anfrage-Thread-Pool delegiert werden), werden die Client-Anfragen niemals zurückgewiesen, so dass es sich aus ihrer Perspektive so anfühlt, als wäre die Skalierung nahtlos.

Diese Art von Entwurf wird durch einen Load Balancer über den Cluster von Dienstinstanzen ergänzt, der den Datenverkehr über sie verteilt (Round Robin oder sogar über einen Mechanismus, bei dem jeder Knoten seine "busy-ness" mit der verwendeten Rückmeldung meldet) Lenken Sie das Verhalten des Lastenausgleichs an, z. B. leiten Sie mehr Verkehr zu NodeA, weil dieser zu wenig genutzt wird, und weniger Verkehr zu NodeB, weil er zu stark ausgelastet ist.

Die obige Beschreibung eines nicht blockierenden Dienstes kratzt nur die Oberfläche; Es gibt viel mehr zu ihnen (und viele Dokumente, Blog-Postings, hilfreiche Bits-n-Stücke im Internet), aber angesichts Ihrer Problemstellung (Bedenken über serverseitige Ressourcen angesichts der zunehmenden Belastung von einem Client) klingt es wie ein gutes passen.

+0

das ist ein guter Vorschlag. Wird mehr darüber erfahren – jubin

Verwandte Themen