Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

In seinem Bericht erzählt Ihnen Andrey Borodin, wie sie die Erfahrungen mit der Skalierung von PgBouncer bei der Gestaltung des Verbindungspoolers berücksichtigt haben Odyssey, als sie es in Produktion brachten. Darüber hinaus besprechen wir, welche Funktionen des Pullers wir in neuen Versionen sehen möchten: Es ist uns wichtig, nicht nur unsere Bedürfnisse zu erfüllen, sondern auch die Benutzergemeinschaft zu entwickeln Одиссея.

Video:

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Hallo zusammen! Ich heiße Andrey.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Bei Yandex entwickle ich Open-Source-Datenbanken. Und heute haben wir ein Thema über Connection-Pooler-Verbindungen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wenn Sie wissen, wie man Connection Pooler auf Russisch nennt, dann sagen Sie es mir. Ich möchte unbedingt einen guten Fachbegriff finden, der sich in der Fachliteratur etablieren soll.

Das Thema ist ziemlich kompliziert, da in vielen Datenbanken der Verbindungspooler integriert ist und Sie nicht einmal davon wissen müssen. Natürlich gibt es überall einige Einstellungen, aber in Postgres funktioniert das nicht so. Und parallel dazu (bei HighLoad++ 2019) gibt es einen Bericht von Nikolai Samokhvalov über das Einrichten von Abfragen in Postgres. Und so wie ich es verstehe, kamen Leute hierher, die ihre Abfragen bereits perfekt konfiguriert hatten, und das sind Leute, die mit selteneren Systemproblemen im Zusammenhang mit der Netzwerk- und Ressourcenauslastung konfrontiert sind. Und an manchen Stellen könnte es in dem Sinne ziemlich schwierig sein, dass die Probleme nicht offensichtlich sind.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Yandex hat Postgres. Viele Yandex-Dienste leben in Yandex.Cloud. Und wir haben mehrere Petabyte an Daten, die in Postgres mindestens eine Million Anfragen pro Sekunde generieren.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und wir stellen einen ziemlich standardmäßigen Cluster für alle Dienste bereit – dies ist der primäre Hauptknoten des Knotens, die üblichen zwei Replikate (synchron und asynchron), Sicherung, Skalierung von Leseanforderungen auf der Replik.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Jeder Clusterknoten ist Postgres, auf dem neben Postgres und Überwachungssystemen auch ein Verbindungspooler installiert ist. Verbindungspooler werden für Zäune und für ihren Hauptzweck verwendet.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Was ist der Hauptzweck des Verbindungspoolers?

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Postgres verwendet bei der Arbeit mit einer Datenbank ein Prozessmodell. Das bedeutet, dass eine Verbindung ein Prozess, ein Postgres-Backend ist. Und in diesem Backend gibt es viele verschiedene Caches, deren unterschiedliche Erstellung für verschiedene Verbindungen ziemlich teuer ist.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Darüber hinaus verfügt der Postgres-Code über ein Array namens procArray. Es enthält grundlegende Daten zu Netzwerkverbindungen. Und fast alle procArray-Verarbeitungsalgorithmen weisen eine lineare Komplexität auf; sie laufen über das gesamte Array von Netzwerkverbindungen. Es ist ein ziemlich schneller Zyklus, aber mit mehr eingehenden Netzwerkverbindungen wird es etwas teurer. Und wenn es etwas teurer wird, kann es sein, dass man für viele Netzwerkanschlüsse einen sehr hohen Preis zahlt.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Es gibt 3 mögliche Vorgehensweisen:

  • Auf der Anwendungsseite.
  • Auf der Datenbankseite.
  • Und dazwischen also alle möglichen Kombinationen.

Leider befindet sich der Einbaupooler derzeit in der Entwicklung. Unsere Freunde von PostgreSQL Professional machen das meistens. Wann es erscheinen wird, ist schwer vorherzusagen. Und tatsächlich haben wir für den Architekten zwei Lösungen zur Auswahl. Dies sind der anwendungsseitige Pool und der Proxy-Pool.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Der anwendungsseitige Pool ist der einfachste Weg. Und fast alle Client-Treiber bieten Ihnen eine Möglichkeit: Millionen Ihrer Verbindungen im Code als mehrere Dutzend Verbindungen zur Datenbank darzustellen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Das Problem besteht darin, dass Sie das Backend ab einem bestimmten Punkt skalieren und auf vielen virtuellen Maschinen bereitstellen möchten.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Dann stellen Sie fest, dass Sie über mehrere weitere Verfügbarkeitszonen und mehrere Rechenzentren verfügen. Und der clientseitige Pooling-Ansatz führt zu großen Zahlen. Große sind etwa 10 Verbindungen. Dies ist die Kante, die normal funktionieren kann.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wenn wir über Proxy-Pooler sprechen, dann gibt es zwei Pooler, die viele Dinge tun können. Sie sind nicht nur Pooler. Sie sind Pooler + mehr coole Funktionalität. Das Pgpool и Crunchy-Proxy.

Aber leider benötigt nicht jeder diese zusätzliche Funktionalität. Und es führt dazu, dass Pooler nur Session-Pooling unterstützen, also einen eingehenden Client und einen ausgehenden Client zur Datenbank.

Da dies für unsere Zwecke nicht sehr geeignet ist, verwenden wir PgBouncer, das Transaktionspooling implementiert, d. h. Serververbindungen werden nur für die Dauer der Transaktion mit Clientverbindungen abgeglichen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und bei unserem Arbeitspensum trifft das zu. Aber es gibt ein paar Probleme.Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Die Probleme beginnen, wenn Sie eine Sitzung diagnostizieren möchten, da alle Ihre eingehenden Verbindungen lokal sind. Jeder kam mit einem Loopback und irgendwie wird es schwierig, die Sitzung zurückzuverfolgen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Natürlich können Sie application_name_add_host verwenden. Dies ist eine Möglichkeit auf der Bouncer-Seite, dem Anwendungsnamen eine IP-Adresse hinzuzufügen. Anwendungsname wird jedoch durch eine zusätzliche Verbindung festgelegt.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

In diesem Diagramm stellt die gelbe Linie echte Anfragen dar und die blaue Linie stellt Anfragen dar, die in die Datenbank gelangen. Und dieser Unterschied besteht genau in der Installation von application_name, die nur für die Ablaufverfolgung benötigt wird, aber überhaupt nicht kostenlos ist.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Darüber hinaus können Sie in Bouncer keinen Pool begrenzen, d. h. die Anzahl der Datenbankverbindungen pro bestimmtem Benutzer und pro bestimmter Datenbank.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wozu führt das? Sie haben einen geladenen Dienst, der in C++ geschrieben ist, und irgendwo in der Nähe einen kleinen Dienst auf einem Knoten, der zwar nichts Schlimmes mit der Datenbank macht, aber dessen Treiber verrückt spielt. Es öffnet 20 Verbindungen und alles andere wird warten. Sogar Ihr Code ist normal.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir haben natürlich einen kleinen Patch für Bouncer geschrieben, der diese Einstellung hinzugefügt hat, d. h. die Beschränkung der Clients auf den Pool.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Dies wäre auf der Postgres-Seite möglich, d. h. die Rollen in der Datenbank durch die Anzahl der Verbindungen zu begrenzen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Aber dann verlieren Sie die Fähigkeit zu verstehen, warum Sie keine Verbindung zum Server haben. PgBouncer gibt keinen Verbindungsfehler aus, sondern gibt immer die gleichen Informationen zurück. Und Sie können es nicht verstehen: Vielleicht hat sich Ihr Passwort geändert, vielleicht ist die Datenbank einfach verloren gegangen, vielleicht stimmt etwas nicht. Aber es gibt keine Diagnose. Wenn eine Sitzung nicht aufgebaut werden kann, wissen Sie nicht, warum sie nicht aufgebaut werden kann.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

An einem bestimmten Punkt sehen Sie sich die Anwendungsdiagramme an und stellen fest, dass die Anwendung nicht funktioniert.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Schauen Sie nach oben und sehen Sie, dass Bouncer Single-Threaded ist. Dies ist ein Wendepunkt im Leben des Dienstes. Ihnen wird klar, dass Sie sich darauf vorbereitet haben, die Datenbank in anderthalb Jahren zu skalieren, und dass Sie den Pooler skalieren müssen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir sind zu dem Schluss gekommen, dass wir mehr PgBouncer brauchen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

https://lwn.net/Articles/542629/

Der Bouncer wurde ein wenig gepatcht.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und sie haben dafür gesorgt, dass durch die Wiederverwendung des TCP-Ports mehrere Bouncer aktiviert werden konnten. Und das Betriebssystem überträgt eingehende TCP-Verbindungen automatisch per Round-Robin zwischen ihnen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Dies ist für Clients transparent, was bedeutet, dass es so aussieht, als ob Sie einen Bouncer hätten, die inaktiven Verbindungen zwischen den laufenden Bouncern jedoch fragmentiert sind.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und irgendwann bemerken Sie vielleicht, dass diese 3 Bouncer jeweils ihren Kern zu 100 % auffressen. Sie benötigen eine ganze Reihe von Türstehern. Warum?

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Weil Sie TLS haben. Sie haben eine verschlüsselte Verbindung. Und wenn Sie Postgres mit und ohne TLS vergleichen, werden Sie feststellen, dass die Anzahl der hergestellten Verbindungen bei aktivierter Verschlüsselung um fast zwei Größenordnungen sinkt, da der TLS-Handshake CPU-Ressourcen verbraucht.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und oben sieht man eine ganze Reihe kryptografischer Funktionen, die bei einer Welle eingehender Verbindungen ausgeführt werden. Da unser Primärserver zwischen Verfügbarkeitszonen wechseln kann, ist eine Welle eingehender Verbindungen eine ziemlich typische Situation. Das heißt, aus irgendeinem Grund war die alte Primärdatenbank nicht verfügbar und die gesamte Last wurde an ein anderes Rechenzentrum gesendet. Sie werden alle gleichzeitig kommen, um TLS zu begrüßen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und eine große Anzahl von TLS-Handshakes grüßt den Bouncer möglicherweise nicht mehr, sondern drückt ihm die Kehle zu. Aufgrund des Timeouts kann die Welle eingehender Verbindungen ungedämpft werden. Wenn Sie ohne exponentiellen Backoff erneut versuchen, zur Basis zu gelangen, werden sie nicht immer wieder in einer zusammenhängenden Welle auftauchen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Hier ist ein Beispiel von 16 PgBouncern, die 16 Kerne zu 100 % laden.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir kamen zur Kaskade PgBouncer. Dies ist die beste Konfiguration, die mit Bouncer für unsere Ladung erreicht werden kann. Unsere externen Bouncer werden für den TCP-Handshake verwendet, und interne Bouncer werden für echtes Pooling verwendet, um externe Verbindungen nicht zu stark zu fragmentieren.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

In dieser Konfiguration ist ein reibungsloser Neustart möglich. Sie können alle diese 18 Bouncer einzeln neu starten. Die Aufrechterhaltung einer solchen Konfiguration ist jedoch ziemlich schwierig. Sysadmins, DevOps und Personen, die tatsächlich für diesen Server verantwortlich sind, werden mit dieser Regelung nicht sehr zufrieden sein.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Es scheint, dass alle unsere Verbesserungen auf Open Source übertragen werden können, aber Bouncer wird nicht sehr gut unterstützt. Beispielsweise wurde vor einem Monat die Möglichkeit eingeführt, mehrere PgBouncer auf einem Port auszuführen. Vor einigen Jahren gab es einen Pull-Request mit dieser Funktion.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

https://www.postgresql.org/docs/current/libpq-cancel.html

https://github.com/pgbouncer/pgbouncer/pull/79

Oder noch ein Beispiel. In Postgres können Sie eine laufende Anfrage abbrechen, indem Sie das Geheimnis ohne unnötige Authentifizierung an eine andere Verbindung senden. Einige Clients senden jedoch einfach einen TCP-Reset, d. h. sie unterbrechen die Netzwerkverbindung. Was wird Bouncer tun? Er wird nichts tun. Die Anfrage wird weiterhin ausgeführt. Wenn Sie eine große Anzahl von Verbindungen erhalten haben, die eine Datenbank mit kleinen Anfragen erstellt haben, reicht es nicht aus, einfach die Verbindung von Bouncer zu trennen; Sie müssen auch die Anfragen abschließen, die in der Datenbank ausgeführt werden.

Dies wurde behoben und dieses Problem wurde noch nicht in den Upstream von Bouncer integriert.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und so kamen wir zu dem Schluss, dass wir einen eigenen Verbindungspooler brauchen, der entwickelt und gepatcht wird, in dem Probleme schnell behoben werden können und der natürlich multithreadfähig sein muss.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir legen Multithreading als Hauptaufgabe fest. Wir müssen in der Lage sein, die Welle eingehender TLS-Verbindungen gut zu bewältigen.

Dazu mussten wir eine separate Bibliothek namens Machinarium entwickeln, die die Maschinenzustände einer Netzwerkverbindung als sequentiellen Code beschreiben soll. Wenn Sie sich den libpq-Quellcode ansehen, werden Sie einige ziemlich komplexe Aufrufe sehen, die Ihnen ein Ergebnis zurückgeben und sagen können: „Rufen Sie mich später an.“ Im Moment habe ich vorerst E/A, aber wenn die E/A wegfällt, werde ich den Prozessor belasten.“ Und das ist ein mehrstufiges Schema. Die Netzwerkkommunikation wird üblicherweise durch eine Zustandsmaschine beschrieben. Viele Regeln wie „Wenn ich zuvor einen Paket-Header der Größe N erhalten habe, warte ich jetzt auf N Bytes“, „Wenn ich ein SYNC-Paket gesendet habe, warte ich jetzt auf ein Paket mit Ergebnismetadaten.“ Das Ergebnis ist ein ziemlich schwieriger, kontraintuitiver Code, als ob das Labyrinth in Zeilenscan umgewandelt würde. Wir haben dafür gesorgt, dass der Programmierer anstelle einer Zustandsmaschine den Hauptpfad der Interaktion in Form eines gewöhnlichen imperativen Codes beschreibt. Es ist nur so, dass Sie in diesem zwingenden Code Stellen einfügen müssen, an denen die Ausführungssequenz unterbrochen werden muss, indem auf Daten aus dem Netzwerk gewartet wird, und den Ausführungskontext an eine andere Coroutine (grüner Thread) übergeben. Dieser Ansatz ähnelt der Tatsache, dass wir den am meisten erwarteten Pfad im Labyrinth nacheinander aufschreiben und ihm dann Zweige hinzufügen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Infolgedessen haben wir einen Thread, der TCP akzeptiert, und Round-Robin leitet die TPC-Verbindung an viele Worker weiter.

In diesem Fall läuft jede Client-Verbindung immer auf einem Prozessor. Und so können Sie es Cache-freundlich gestalten.

Darüber hinaus haben wir die Zusammenfassung kleiner Pakete zu einem großen Paket leicht verbessert, um den TCP-Stack des Systems zu entlasten.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Darüber hinaus haben wir das Transaktionspooling in dem Sinne verbessert, dass Odyssey bei Konfiguration CANCEL und ROLLBACK im Falle eines Netzwerkverbindungsfehlers senden kann, d. h. wenn niemand auf eine Anfrage wartet, weist Odyssey die Datenbank an, dies nicht zu versuchen Erfüllen Sie die Anfrage, die möglicherweise wertvolle Ressourcen verschwendet.

Und wann immer möglich halten wir die Verbindung zum selben Kunden aufrecht. Dadurch wird eine Neuinstallation von application_name_add_host vermieden. Wenn dies möglich ist, müssen wir die für die Diagnose erforderlichen Parameter nicht zusätzlich neu einstellen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir arbeiten im Interesse von Yandex.Cloud. Und wenn Sie verwaltetes PostgreSQL verwenden und einen Verbindungspooler installiert haben, können Sie eine logische Replikation nach außen erstellen, d. h. uns, wenn Sie möchten, die logische Replikation überlassen. Bouncer gibt den logischen Replikationsfluss nicht nach außen frei.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Dies ist ein Beispiel für die Einrichtung einer logischen Replikation.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Darüber hinaus unterstützen wir die physische Replikation nach außen. In der Cloud ist das natürlich nicht möglich, da der Cluster dann zu viele Informationen über sich selbst liefert. Wenn Sie jedoch in Ihren Installationen eine physische Replikation über den Verbindungspooler in Odyssey benötigen, ist dies möglich.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Odyssey verfügt über eine vollständig kompatible Überwachung mit PgBouncer. Wir haben dieselbe Konsole, die fast alle dieselben Befehle ausführt. Wenn etwas fehlt, senden Sie eine Pull-Anfrage oder zumindest einen Issue auf GitHub, und wir führen die erforderlichen Befehle aus. Aber wir verfügen bereits über die Hauptfunktionalität der PgBouncer-Konsole.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und natürlich gibt es bei uns auch eine Fehlerweiterleitung. Wir geben den von der Datenbank gemeldeten Fehler zurück. Sie erhalten Informationen darüber, warum Sie nicht in der Datenbank enthalten sind und nicht nur darüber, dass Sie nicht darin enthalten sind.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Diese Funktion ist deaktiviert, falls Sie 100 % Kompatibilität mit PgBouncer benötigen. Wir können uns sicherheitshalber genauso verhalten wie Bouncer.

Entwicklung

Ein paar Worte zum Odyssey-Quellcode.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/66

Es gibt beispielsweise „Pause/Fortsetzen“-Befehle. Sie werden normalerweise zum Aktualisieren der Datenbank verwendet. Wenn Sie Postgres aktualisieren müssen, können Sie es im Verbindungspooler anhalten, pg_upgrade ausführen und dann fortfahren. Und aus Sicht des Kunden wird es so aussehen, als würde die Datenbank einfach langsamer werden. Diese Funktionalität wurde uns von Leuten aus der Community zur Verfügung gestellt. Sie ist noch nicht gefroren, aber bald wird alles gefroren sein. (Bereits gefroren)

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

https://github.com/yandex/odyssey/pull/73 - bereits gefroren

Darüber hinaus ist eine der neuen Funktionen in PgBouncer die Unterstützung der SCRAM-Authentifizierung, die uns auch von einer Person mitgeteilt wurde, die nicht in Yandex.Cloud arbeitet. Beides ist funktionell komplex und wichtig.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Deshalb möchte ich Ihnen sagen, woraus Odyssey besteht, falls Sie jetzt auch ein wenig Code schreiben möchten.

Sie verfügen über die Odyssey-Quellenbasis, die auf zwei Hauptbibliotheken basiert. Die Kiwi-Bibliothek ist eine Implementierung des Postgres-Nachrichtenprotokolls. Das heißt, natives Proto 3 von Postgres sind Standardnachrichten, die Front-Ends und Back-Ends austauschen können. Sie sind in der Kiwi-Bibliothek implementiert.

Die Machinarium-Bibliothek ist eine Thread-Implementierungsbibliothek. Ein kleiner Ausschnitt dieses Machinariums ist in Assemblersprache geschrieben. Aber seien Sie nicht beunruhigt, es gibt nur 15 Zeilen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Odyssee-Architektur. Es gibt einen Hauptrechner, auf dem Coroutinen laufen. Diese Maschine implementiert die Annahme eingehender TCP-Verbindungen und deren Verteilung an die Mitarbeiter.

Ein Handler für mehrere Clients kann innerhalb eines Workers arbeiten. Der Hauptthread führt außerdem die Konsole und die Verarbeitung von Crone-Aufgaben aus, um Verbindungen zu löschen, die im Pool nicht mehr benötigt werden.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Odyssey wird mit der Standard-Postgres-Testsuite getestet. Wir führen einfach die Installationsprüfung über Bouncer durch und über Odyssey erhalten wir ein Null-Div. Es gibt mehrere Tests im Zusammenhang mit der Datumsformatierung, die in Bouncer und Odyssey nicht genau die gleichen Ergebnisse liefern.

Darüber hinaus gibt es viele Fahrer, die eigene Tests durchführen. Und wir nutzen ihre Tests, um die Odyssee zu testen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Darüber hinaus müssen wir aufgrund unserer Kaskadenkonfiguration verschiedene Bundles testen: Postgres + Odyssey, PgBouncer + Odyssey, Odyssey + Odyssey, um sicherzustellen, dass Odyssey auch dann noch funktioniert, wenn er in einem der Teile der Kaskade gelandet ist wie wir es erwarten.

Rechen

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Wir verwenden Odyssey in der Produktion. Und es wäre nicht fair, wenn ich sagen würde, dass alles einfach funktioniert. Nein, das heißt ja, aber nicht immer. In der Produktion funktionierte zum Beispiel einfach alles, dann kamen unsere Freunde von PostgreSQL Professional und sagten, wir hätten einen Speicherverlust. Das stimmt wirklich, wir haben sie korrigiert. Aber es war einfach.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Dann haben wir festgestellt, dass der Verbindungspooler eingehende und ausgehende TLS-Verbindungen hat. Und Verbindungen erfordern Client-Zertifikate und Server-Zertifikate.

Bouncer- und Odyssey-Serverzertifikate werden von ihrem PCache erneut gelesen, Client-Zertifikate müssen jedoch nicht erneut aus dem PCache gelesen werden, da unser skalierbarer Odyssey letztendlich die Systemleistung beim Lesen dieses Zertifikats beeinträchtigt. Das kam für uns überraschend, denn es dauerte nicht lange, bis er Widerstand leistete. Zunächst skalierte es linear, aber nach 20 gleichzeitig eingehenden Verbindungen zeigte sich dieses Problem.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Bei der steckbaren Authentifizierungsmethode handelt es sich um die Möglichkeit zur Authentifizierung mithilfe integrierter Lunux-Tools. In PgBouncer ist es so implementiert, dass es einen separaten Thread gibt, der auf eine Antwort von PAM wartet, und es einen Haupt-PgBouncer-Thread gibt, der die aktuelle Verbindung bedient und sie bitten kann, im PAM-Thread zu leben.

Wir haben dies aus einem einfachen Grund nicht umgesetzt. Wir haben viele Threads. Warum brauchen wir das?

Dies kann letztendlich zu Problemen führen, da bei einer PAM-Authentifizierung und einer Nicht-PAM-Authentifizierung eine große Welle der PAM-Authentifizierung die Nicht-PAM-Authentifizierung erheblich verzögern kann. Dies ist eines der Dinge, die wir nicht behoben haben. Aber wenn Sie das Problem beheben möchten, können Sie dies tun.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Ein weiterer Vorteil bestand darin, dass wir einen Thread haben, der alle eingehenden Verbindungen akzeptiert. Anschließend werden sie in den Worker-Pool übertragen, wo der TLS-Handshake stattfindet.

Fazit: Wenn Sie eine zusammenhängende Welle von 20 Netzwerkverbindungen haben, werden diese alle akzeptiert. Und auf der Clientseite beginnt libpq mit der Meldung von Zeitüberschreitungen. Standardmäßig scheint es 000 Sekunden zu sein.

Wenn nicht alle gleichzeitig die Datenbank betreten können, können sie die Datenbank nicht betreten, da dies alles durch nicht-exponentielle Wiederholungsversuche abgedeckt werden kann.

Wir kamen zu dem Schluss, dass wir das Schema von PgBouncer hier kopiert haben, mit der Tatsache, dass wir die Anzahl der TCP-Verbindungen, die wir akzeptieren, drosseln.

Wenn wir feststellen, dass wir Verbindungen annehmen, diese aber letztendlich keine Zeit zum Handshake haben, stellen wir sie in eine Warteschlange, damit sie keine CPU-Ressourcen verschwenden. Dies führt dazu, dass möglicherweise nicht für alle eingegangenen Verbindungen ein gleichzeitiger Handshake durchgeführt wird. Aber immerhin greift jemand auf die Datenbank zu, auch wenn die Belastung recht hoch ist.

Roadmap

Was würden Sie gerne in der Zukunft in Odyssey sehen? Was sind wir bereit, uns weiterzuentwickeln und was erwarten wir von der Gemeinschaft?

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Stand August 2019.

So sah die Odyssey-Roadmap im August aus:

  • Wir wollten SCRAM- und PAM-Authentifizierung.
  • Wir wollten Leseanfragen an den Standby weiterleiten.
  • Ich möchte einen Online-Neustart.
  • Und die Möglichkeit, auf dem Server zu pausieren.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Die Hälfte dieser Roadmap wurde fertiggestellt, und zwar nicht von uns. Und das ist gut. Lassen Sie uns also besprechen, was noch übrig ist, und weitere hinzufügen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Bezüglich der Weiterleitung schreibgeschützter Abfragen an den Standby-Modus? Wir haben Nachbildungen, die einfach die Luft erwärmen, ohne dass Anforderungen ausgeführt werden müssen. Wir benötigen sie, um Failover und Switchover bereitzustellen. Sollte es in einem der Rechenzentren zu Problemen kommen, würde ich diese gerne mit nützlichen Arbeiten beschäftigen. Denn wir können nicht dieselben Zentralprozessoren, denselben Speicher unterschiedlich konfigurieren, da sonst die Replikation nicht funktioniert.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Grundsätzlich ist es in Postgres ab 10 möglich, beim Herstellen einer Verbindung session_attrs anzugeben. Sie können alle Datenbankhosts in der Verbindung auflisten und angeben, warum Sie auf die Datenbank zugreifen: Schreib- oder Lesezugriff. Und der Fahrer selbst wählt den ersten Host in der Liste aus, der ihm am besten gefällt und der die Anforderungen von session_attrs erfüllt.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Das Problem bei diesem Ansatz besteht jedoch darin, dass er die Replikationsverzögerung nicht kontrolliert. Möglicherweise verfügen Sie über ein Replikat, das für Ihren Dienst unzumutbar lange im Rückstand ist. Um die Ausführung von Leseabfragen auf einem Replikat mit vollem Funktionsumfang zu ermöglichen, müssen wir im Wesentlichen die Fähigkeit von Odyssey unterstützen, nicht auszuführen, wenn es nicht gelesen werden kann.

Odyssey muss von Zeit zu Zeit zur Datenbank gehen und nach der Replikationsentfernung von der Primärdatenbank fragen. Und wenn der Grenzwert erreicht ist, lassen Sie keine neuen Anfragen in die Datenbank zu, teilen Sie dem Client mit, dass er Verbindungen neu initiieren muss und wählen Sie möglicherweise einen anderen Host aus, um Anfragen auszuführen. Dadurch kann die Datenbank die Replikationsverzögerung schnell wiederherstellen und erneut mit einer Anfrage antworten.

Es ist schwierig, einen Zeitrahmen für die Implementierung anzugeben, da es sich um Open Source handelt. Aber ich hoffe, nicht 2,5 Jahre wie meine Kollegen von PgBouncer. Das ist die Funktion, die ich mir in der Odyssee wünschen würde.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

In der Community wurde nach Unterstützung für die vorbereitete Stellungnahme gefragt. Jetzt können Sie eine vorbereitete Erklärung auf zwei Arten erstellen. Zunächst können Sie den SQL-Befehl „prepared“ ausführen. Um diesen SQL-Befehl zu verstehen, müssen wir lernen, die SQL auf der Bouncer-Seite zu verstehen. Das wäre übertrieben, denn es ist übertrieben, da wir den gesamten Parser benötigen. Wir können nicht jeden SQL-Befehl analysieren.

Auf Proto3 gibt es jedoch eine vorbereitete Anweisung auf Nachrichtenprotokollebene. Und hier kommt die Information, dass eine vorbereitete Erklärung erstellt wird, in strukturierter Form an. Und wir könnten das Verständnis unterstützen, dass der Client bei einer Serververbindung darum gebeten hat, vorbereitete Anweisungen zu erstellen. Und selbst wenn die Transaktion abgeschlossen ist, müssen wir die Konnektivität zwischen dem Server und dem Client aufrechterhalten.

Aber hier entsteht eine Diskrepanz im Dialog, weil jemand sagt, dass man verstehen muss, welche Art von vorbereiteten Anweisungen der Client erstellt hat, und die Serververbindung zwischen allen Clients teilen muss, die diese Serververbindung erstellt haben, d. h. wer eine solche vorbereitete Erklärung erstellt hat.

Andres Freund sagte, wenn ein Kunde zu Ihnen kommt, der bereits eine solche vorbereitete Anweisung in einer anderen Serververbindung erstellt hat, dann erstellen Sie sie für ihn. Es scheint jedoch etwas falsch zu sein, Abfragen in der Datenbank statt im Client auszuführen, aber aus Sicht des Entwicklers, der das Protokoll für die Interaktion mit der Datenbank schreibt, wäre es praktisch, wenn ihm einfach eine Netzwerkverbindung gegeben würde, in der Es gibt eine solche vorbereitete Abfrage.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Und noch eine Funktion, die wir implementieren müssen. Wir haben jetzt eine mit PgBouncer kompatible Überwachung. Wir können die durchschnittliche Ausführungszeit einer Abfrage zurückgeben. Aber die durchschnittliche Zeit ist die durchschnittliche Temperatur im Krankenhaus: Manche sind kalt, manche sind warm – im Durchschnitt sind alle gesund. Es ist nicht wahr.

Wir müssen Unterstützung für Perzentile implementieren, die darauf hinweisen, dass es langsame Abfragen gibt, die Ressourcen verschwenden, und die Überwachung akzeptabler machen.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Das Wichtigste ist, dass ich Version 1.0 möchte (Version 1.1 wurde bereits veröffentlicht). Fakt ist, dass Odyssey mittlerweile in der Version 1.0rc, also Release Candidate, vorliegt. Und alle von mir aufgeführten Probleme wurden bis auf den Speicherverlust mit genau derselben Version behoben.

Was bedeutet Version 1.0 für uns? Wir führen Odyssey zu unseren Stützpunkten ein. Es läuft bereits in unseren Datenbanken, aber wenn es den Punkt von 1 Anfragen pro Sekunde erreicht, können wir sagen, dass dies die Release-Version ist und dass es sich um eine Version handelt, die als 000 bezeichnet werden kann.

Mehrere Leute in der Community haben darum gebeten, dass Version 1.0 Pause und SCRAM beinhaltet. Dies bedeutet jedoch, dass wir die nächste Version in Produktion bringen müssen, da weder SCRAM noch Pause deaktiviert wurden. Aber höchstwahrscheinlich wird dieses Problem recht schnell gelöst.

Odyssey-Roadmap: Was wollen wir sonst noch von einem Verbindungspooler? Andrey Borodin (2019)

Ich warte auf Ihre Pull-Anfrage. Ich würde auch gerne hören, welche Probleme Sie mit Bouncer haben. Lassen Sie uns darüber diskutieren. Vielleicht können wir einige Funktionen implementieren, die Sie benötigen.

Dies ist das Ende meines Teils, ich würde Ihnen gerne zuhören. Danke!

Fragen

Wenn ich meinen eigenen Anwendungsnamen festlege, wird dieser korrekt weitergeleitet, auch beim Transaktions-Pooling in Odyssey?

Odyssee oder Türsteher?

In Odyssee. Im Bouncer wird geworfen.

Wir machen ein Set.

Und wenn meine echte Verbindung auf andere Verbindungen springt, wird sie dann übertragen?

Wir erstellen einen Satz aller Parameter, die in der Liste aufgeführt sind. Ich kann nicht sagen, ob Anwendungsname in dieser Liste enthalten ist. Ich glaube, ich habe ihn dort gesehen. Wir werden alle gleichen Parameter einstellen. Mit einer Anfrage erledigt das Set alles, was vom Client beim Start installiert wurde.

Danke, Andrey, für den Bericht! Guter Bericht! Ich bin froh, dass sich Odyssey von Minute zu Minute schneller weiterentwickelt. Ich möchte so weitermachen. Wir haben Sie bereits um eine Verbindung mit mehreren Datenquellen gebeten, damit Odyssey gleichzeitig eine Verbindung zu verschiedenen Datenbanken herstellen kann, d. h. zu einem Master-Slave, und nach einem Failover automatisch eine Verbindung zu einem neuen Master herstellen kann.

Ja, ich scheine mich an diese Diskussion zu erinnern. Mittlerweile gibt es mehrere Speicher. Aber es gibt keinen Wechsel zwischen ihnen. Auf unserer Seite müssen wir den Server abfragen, ob er noch aktiv ist, und verstehen, dass ein Failover stattgefunden hat, der pg_recovery aufruft. Ich verstehe standardmäßig, dass wir nicht zum Meister gekommen sind. Und sollen wir aus den Fehlern irgendwie etwas verstehen oder was? Das heißt, die Idee ist interessant, sie wird diskutiert. Schreiben Sie weitere Kommentare. Wenn Sie Mitarbeiter haben, die C beherrschen, dann ist das großartig.

Auch das Thema der Skalierung über Replikate hinweg ist für uns von Interesse, da wir Anwendungsentwicklern die Einführung replizierter Cluster so einfach wie möglich machen möchten. Aber hier hätte ich gerne mehr Kommentare, also genau, wie man es macht, wie man es gut macht.

Die Frage betrifft auch Nachbildungen. Es stellt sich heraus, dass Sie einen Master und mehrere Replikate haben. Und es ist klar, dass sie für Verbindungen seltener zum Replikat als zum Master gehen, weil es Unterschiede geben kann. Sie sagten, dass der Unterschied in den Daten so groß sein könnte, dass er Ihr Unternehmen nicht zufriedenstellt und Sie nicht dorthin gelangen, bis er repliziert wurde. Wenn Sie jedoch längere Zeit nicht dorthin gegangen sind und dann losgefahren sind, sind die benötigten Daten nicht sofort verfügbar. Das heißt, wenn wir ständig zum Master gehen, wird der Cache dort aufgewärmt, aber im Replikat bleibt der Cache etwas zurück.

Ja es ist wahr. Der PCache verfügt nicht über die gewünschten Datenblöcke, der echte Cache enthält keine Informationen zu den gewünschten Tabellen, die Pläne enthalten keine analysierten Abfragen, es gibt überhaupt nichts.

Und wenn Sie eine Art Cluster haben und dort ein neues Replikat hinzufügen, ist beim Start alles darin fehlerhaft, d. h. es vergrößert seinen Cache.

Ich habe die Idee. Der richtige Ansatz wäre, zuerst einen kleinen Prozentsatz der Abfragen auf dem Replikat auszuführen, um den Cache aufzuwärmen. Grob gesagt haben wir die Bedingung, dass wir nicht mehr als 10 Sekunden hinter dem Meister zurückbleiben dürfen. Und dieser Zustand ist nicht in einer Welle enthalten, sondern für einige Kunden reibungslos.

Ja, Gewicht erhöhen.

Das ist eine gute Idee. Aber zuerst müssen wir diesen Shutdown umsetzen. Zuerst müssen wir es ausschalten, und dann überlegen wir, wie wir es einschalten. Dies ist eine großartige Funktion, die reibungslos aktiviert werden kann.

Nginx hat diese Option slowly start in einem Cluster für den Server. Und er steigert nach und nach die Belastung.

Ja, tolle Idee, wir werden es versuchen, wenn wir dazu kommen.

Source: habr.com

Kommentar hinzufügen