Zum Inhalt springen

Was verwaltetes Postgres für Laravel ändert

Serverless-Postgres ist für Lasten mit einer Verbindung je Anfrage geformt. Laravel hält langlebige Verbindungen in seinen Queue-Workern, und dort liegen die Überraschungen.

4 Min. Lesezeit

Verwaltetes Postgres hieß früher: ein Server, den jemand anders patcht. Zunehmend heißt es Plattform - Speicher getrennt von Compute, Verbindungen über einen Pooler vermittelt, Datenbanken, die sich wie Git verzweigen, und Compute, das suspendiert, wenn niemand fragt.

All das ist für eine Last gebaut, bei der eine Anfrage eintrifft, eine Abfrage ausführt und verschwindet. Laravel ist genau diese Last auf der Web-Schicht und überall sonst das Gegenteil.

Die Diskrepanz, klar benannt

Eine Laravel-Anwendung hat drei Arten von Datenbank-Client, und sie verhalten sich völlig unterschiedlich:

Web-Anfragen. PHP-FPM, Verbindung auf und zu je Anfrage. Das passt exakt zum Serverless-Modell.

Queue-Worker. queue:work verbindet beim Start und hält diese Verbindung sein ganzes Leben, ob er gerade etwas verarbeitet oder nicht. Zwanzig Worker sind zwanzig dauerhafte Verbindungen, bevor ein einziger Besucher eintrifft.

Der Scheduler. Ein Cron-Eintrag, der schedule:run jede Minute ausführt, für immer.

Anbieter bepreisen und dimensionieren um den ersten Fall. Der zweite füllt ein Verbindungskontingent und ist die häufigste Ursache eines SQLSTATE[HY000] [1040] Too many connections - ein Fehler, den wir auf unseren englischsprachigen Fehlerseiten im Einzelnen aufschlüsseln. Der dritte hebelt Scale-to-Zero still aus.

Scale-to-Zero und der Scheduler

Das bekommen die meisten zuerst falsch, und es ist Arithmetik, keine Meinung.

Compute suspendiert nach einer Leerlaufzeit. schedule:run setzt jede Minute eine Abfrage ab. Ist die Leerlaufschwelle länger als eine Minute, suspendiert die Datenbank nie, und Sie zahlen für dauerhaft laufendes Compute mit Kaltstart-Eigenschaften obendrauf.

Es gibt drei ehrliche Antworten. Akzeptieren und für Dauerbetrieb dimensionieren - dann ist eine konventionelle Instanz womöglich günstiger. Den Scheduler auf etwas verlagern, das die Datenbank nicht anfasst, wenn nichts ansteht - was heißt, dass der Zeitplan ohne Abfrage lesbar sein muss. Oder Kaltstarts in einer Testumgebung akzeptieren und in Produktion nicht, wo Scale-to-Zero sich wirklich auszahlt.

Niemand sollte das von einer Rechnung erfahren.

Pooling-Modi, und damit das, was bricht

Jedes Serverless-Postgres setzt einen Pooler davor. Der Modus entscheidet, was Ihre Anwendung darf.

Session Pooling gibt Ihnen eine echte Backend-Verbindung für die Dauer Ihrer Verbindung. Alles funktioniert. Sie bekommen auch weit weniger effektive Verbindungen, was meist der Grund war, warum Sie kamen.

Transaction Pooling gibt Ihnen ein Backend nur für die Dauer einer Transaktion. Das liefert Tausende Client-Verbindungen über wenige echte und entfernt alles, was über Anweisungen hinweg reicht:

  • Serverseitig vorbereitete Statements, die PDO standardmäßig nutzt. Das trifft Laravel speziell, und die Behebung ist ein Flag in der Verbindungszeichenkette oder eine Emulationseinstellung statt einer Codeänderung - sie muss aber bewusst gesetzt werden.
  • Advisory Locks, also können withoutOverlapping() an einem Zeitplan und ShouldBeUnique an einem Job sich anders verhalten als geschrieben, wenn sie über die Datenbank laufen.
  • SET-Anweisungen, sodass alles, was je Verbindung eine Zeitzone oder einen Suchpfad setzt, nicht mehr hält.
  • LISTEN/NOTIFY und jeder langlebige Cursor.

Die praktische Anordnung sind zwei Verbindungen in config/database.php: der gepoolte Endpunkt für Web-Anfragen, der direkte für Migrationen, Queue-Worker und alles, was eine Sperre hält. Das sind zehn Zeilen und sie verhindern den größten Teil dieses Artikels.

Branching, die wirklich neue Fähigkeit

Ein Branch ist eine Copy-on-Write-Datenbank in Produktionsgröße, in Sekunden erzeugt. Für Laravel landet das auf einem konkreten Problem: Migrationen, die gegen vierzig Zeilen sicher sind und gegen vier Millionen vier Minuten sperren.

Ein Branch je Pull Request, Migrationen im CI dagegen ausgeführt, die Dauer protokolliert. Jetzt scheitert eine gefährliche Schemaänderung an einem Build statt an einem Deployment. Das ist das stärkste Argument für eine Plattform gegenüber einer Instanz, und es wiegt mehr als das Preismodell.

Zwischen ihnen wählen

Eine konventionelle verwaltete Instanz - RDS, Cloud SQL, das schlichte Postgres eines Anbieters - wenn die Anwendung eine stetige Worker-Flotte hat, wenn Sie vorhersehbare Verbindungszahlen wollen, und wenn der Betriebsaufwand, den Sie wegkaufen, das Patchen ist und nicht das Skalieren. Für die meisten Geschäftsanwendungen ist das weiterhin richtig, und es ist unmodisch, das zu sagen.

Serverless-Postgres mit Branching, wenn Ihnen die Migrationsprüfung wichtig ist, wenn Umgebungen zahlreich und kurzlebig sind, oder wenn der Verkehr wirklich stoßweise kommt. Planen Sie die Pooling-Arbeit ein, statt sie für eine Änderung an der Verbindungszeichenkette zu halten.

Eine Plattform mit Auth und Storage daran, wenn Sie diese ebenfalls nutzen. Nutzen Sie sie nur als Datenbank, wählen Sie einen Postgres-Anbieter und sollten ihn als solchen vergleichen.

Alles MySQL-Kompatible, aber Geshardete nur mit zuvor gelesener Einschränkungsliste. Referenzielle Integrität, Transaktionen über Shards hinweg und ORDER BY über eine geshardete Tabelle sind die Stellen, an denen das Modell durchscheint, und Laravel-Migrationen schreiben bereitwillig DDL, das die Plattform annimmt und nicht durchsetzt.

Die Prüfung, die einen Nachmittag kostet

Bevor Sie sich festlegen, führen Sie das Echte aus: eine Migration mit Indexaufbau auf einer produktionsgroßen Tabelle, Ihre tatsächliche Worker-Zahl gleichzeitig verbunden, und einen geplanten Befehl, der eine Sperre hält. Drei Messungen, ein Nachmittag.

Jedes Problem in diesem Artikel ist so günstig zu finden und im zweiten Monat teuer.

Verwandte Fragen

Funktioniert Scale-to-Zero mit einer Laravel-Anwendung?
Selten, und aus einem leicht zu übersehenden Grund: der Scheduler läuft jede Minute. Ein `schedule:run`-Cron-Eintrag ist eine Abfrage alle sechzig Sekunden, die Compute wird also nie lange genug untätig, um zu suspendieren. Sie bekommen das Kaltstartverhalten ohne die Ersparnis, sofern Sie nicht bewusst für ruhige Phasen sorgen.
Brauchen wir trotzdem einen Pooler?
Fast sicher, und entscheidend ist der Modus. Transaction Pooling gibt Ihnen die Verbindungszahl und bricht alles, was eine Sitzung voraussetzt - Advisory Locks, `SET`-Anweisungen, `LISTEN/NOTIFY` und serverseitig vorbereitete Statements, die PDO standardmäßig nutzt. Session Pooling behält das alles und gibt weit weniger zurück.
Lohnt sich Datenbank-Branching?
Um Migrationen gegen produktionsförmige Daten zu testen, ja, und es ist die lohnendste Eigenschaft, die eine konventionelle Instanz nicht bieten kann. Ein Branch je Pull Request heißt, dass eine gefährliche Migration im CI gegen echte Zeilenzahlen auffällt statt gegen eine Tabelle mit vierzig Zeilen.
Was ist mit PlanetScale und ähnlichen Vitess-Plattformen?
Sie sind MySQL-kompatibel statt Postgres, und die wesentliche Einschränkung waren historisch Fremdschlüssel - das Sharding-Modell macht referenzielle Integrität über Shards hinweg teuer, und die Unterstützung hat sich über die Zeit geändert. Prüfen Sie das aktuelle Verhalten, bevor Sie `constrained()` in eine Migration schreiben, denn ein akzeptierter und nicht durchgesetzter Fremdschlüssel ist schlimmer als ein abgelehnter.

← Zurück zu allen Artikeln

Anrufen+1 848 272 7583WhatsApp+90 850 308 5436E-Mailinfo@codefacture.comKontaktseite