Blog

Datenbanken aufwecken, ohne tote Verbindungen

Veröffentlichte Apps auf Mythex und ihre Datenbanken gehen schlafen, wenn sie niemand nutzt. Wenn eine App aufwachte, konnte sie die erste Anfrage 10 bis 12 Sekunden lang festhalten, weil sie versuchte, Datenbankverbindungen wiederzuverwenden, die während des allgemeinen Schlafs gestorben waren. Jetzt geben wir Spring-Boot-Apps Datenbankeinstellungen, die den Schlaf überstehen, und weisen den Agenten an, Apps jedes Stacks genauso zu bauen. Auf der Hosting-Plattform sank die Zeit bis zur ersten Antwort nach dem Aufwachen von 12,7 Sekunden auf 2,3 Sekunden.

Warum Apps und Datenbanken schlafen

Eine veröffentlichte Mythex-App läuft auf einer Maschine, die nach einigen Minuten Leerlauf pausiert, und ihre Datenbank ist serverloses Postgres, das nach fünf Minuten Leerlauf schlafen geht und bei der nächsten Anfrage aufwacht. Das hält eine ruhige App günstig: Sie zahlen für das, was die Datenbank tatsächlich genutzt hat, und eine schlafende App verbraucht keine Rechenleistung. Über die Abrechnungsseite haben wir in Datenbanken nach tatsächlicher Nutzung abrechnen geschrieben.

Der Haken: Die beiden schlafen getrennt, und sie sind sich nicht einig, was eine Verbindung ist.

Das Symptom: ein langsamer erster Besuch

Die meisten Server-Apps halten einen Verbindungspool: eine Handvoll offener Datenbankverbindungen, die bereitstehen, damit jede Anfrage nicht die Kosten für das Öffnen einer neuen tragen muss. Das ist das richtige Design für eine App, die immer läuft.

So sieht der Ablauf mit Schlaf aus:

  1. Die App läuft, mit einigen ungenutzten Verbindungen in ihrem Pool.
  2. Niemand besucht sie. Die Maschine der App pausiert, eingefroren, mit intaktem Pool.
  3. Die Datenbank geht schlafen und schließt ihr Ende jeder Verbindung.
  4. Ein Besucher kommt. Die App erwacht genau so, wie sie war, und hält noch Verbindungen, die die Datenbank nicht mehr kennt.
  5. Der Pool gibt eine dieser Verbindungen heraus. Sie muss erst herausfinden, dass sie tot ist, indem sie es versucht und wartet, bevor sie sie aufgibt.

In einer Spring-Boot-App blockierte das Prüfen dieser toten Verbindungen die erste Anfrage rund 10 Sekunden, bevor sie mit „Connection is not available“ fehlschlug. Für den Besucher hing die Seite einfach und zeigte dann vielleicht einen Fehler.

Warum es Spring-Apps am schlimmsten traf

Spring Boot ist ein beliebtes Java-Framework, und es nutzt standardmäßig einen Verbindungspool namens HikariCP. Spring kann diesen Pool über Einstellungen konfigurieren, auch wie viele ungenutzte Verbindungen gehalten werden.

Mythex gibt jeder App ihre Datenbank aber als einzelne DATABASE_URL im Format postgresql://user:pass@host/db. Spring kann dieses Format nicht direkt lesen. Also haben Spring-Apps auf Mythex ihren eigenen Pool im Code aufgebaut, indem sie diese URL zerlegt haben, und ein von Hand gebauter Pool ignoriert alle spring.datasource.*-Einstellungen von Spring. Selbst wenn jemand die richtigen Poolwerte gekannt hätte, hätten sie nirgends gewirkt.

Die Korrektur, Teil 1: Einstellungen, die Spring nutzen kann

Wenn ein Projekt eine Datenbank hat, bekommt es jetzt außerdem Umgebungsvariablen, die Spring nativ liest:

  • SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME und SPRING_DATASOURCE_PASSWORD, aus DATABASE_URL umgewandelt (mit erforderlichem SSL, außer die URL sagt etwas anderes).
  • Poolwerte, die den Schlaf überstehen:
EinstellungWertWarum
Mindestanzahl ungenutzter Verbindungen0Zwischen den Anfragen bleibt nichts offen, also kann nichts veralten
Leerlauf-Timeout30 SekundenUngenutzte Verbindungen bald schließen
Maximale Lebensdauer2 MinutenJede Verbindung ausmustern, bevor sie alt werden kann
Verbindungs-Timeout5 SekundenEine Anfrage nicht lange hängen lassen, wenn die Datenbank langsam antwortet

Da keine ungenutzten Verbindungen gehalten werden, öffnet eine aufgewachte App eine einzige frische Verbindung, statt sich durch tote zu kämpfen.

Sind diese Variablen vorhanden, konfiguriert Spring den Pool selbst, und die Einstellungen greifen. Was das Projekt selbst gesetzt hat, gewinnt immer. Wir füllen nur fehlende Werte aus. Apps, die nicht Spring sind, ignorieren diese Variablen.

Das Detail, das es fast wirkungslos gemacht hätte

Spring ordnet Umgebungsvariablen seinen Einstellungen nach einer Regel zu, die leicht falsch zu machen ist. Die Einstellung minimum-idle muss als SPRING_DATASOURCE_HIKARI_MINIMUMIDLE geschrieben werden: Bindestriche entfallen, Wörter werden zusammengezogen. Schreibt man sie als SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, was natürlicher aussieht, wird daraus eine andere, nicht existierende Einstellung (minimum.idle), und sie wird still ignoriert.

So einen Fehler übersteht jede Prüfung und bewirkt in der Produktion nichts. Deshalb prüft ein Test sowohl, dass die Werte gesetzt sind, als auch, dass keine Variable die Form mit Unterstrichen verwendet.

Die Korrektur, Teil 2: jeder andere Stack

Spring ist nicht das einzige Framework mit einem Pool, und wir können nicht jede Bibliothek in jeder Sprache vorkonfigurieren. Deshalb bekommt der Mythex-Agent, die KI, die Ihre App schreibt, jetzt für jeden Stack eine dauerhafte Anweisung: Veröffentlichte Apps und ihre Datenbanken schlafen, wenn sie untätig sind, deshalb kann eine offen gehaltene Verbindung bei der nächsten Anfrage tot sein. Er sollte:

  • keine ungenutzten Datenbankverbindungen offen halten oder jede vor der Nutzung prüfen,
  • bei einem Verbindungsfehler einmal erneut versuchen und
  • die Datenbankeinstellungen verwenden, die die Plattform in der Umgebung bereitstellt, statt einen eigenen Pool aufzubauen, indem er DATABASE_URL zerlegt.

Der letzte Punkt schließt den Kreis mit Teil 1: Eine App, die die bereitgestellten Einstellungen nutzt, übernimmt die schlafsichere Konfiguration automatisch.

Das Ergebnis

Gemessen auf der Hosting-Plattform, auf der wir veröffentlichte Apps betreiben, sank die erste Antwort nach dem Aufwachen von 12,7 Sekunden auf 2,3 Sekunden.

Was wir daraus mitnehmen

  • Jede Schicht, die schlafen geht, muss sich darüber einig sein, was den Schlaf überlebt. Eine eingefrorene App und eine schlafende Datenbank haben jeweils eine vernünftige Entscheidung getroffen. Zusammen erwachte die App mit einem Zustand, der nicht mehr stimmte.
  • Standards für Dauerbetrieb passen nicht zu Apps, die auf null skalieren. Verbindungen warm zu halten ist eine gute Idee, bis alles drumherum kalt wird.
  • Geben Sie Frameworks ihre Daten in ihrem eigenen Format. Eine URL war für uns einfach und zwang jede Spring-App, einen Pool von Hand zu bauen, der die eigene Konfiguration ignorierte.
  • Prüfen Sie, dass eine Einstellung so geschrieben ist, wie das Framework sie liest. Ein korrekter Wert unter dem falschen Namen bewirkt still nichts.

Wenn Sie neu bei der Funktionsweise von Datenbanken auf Mythex sind, lesen Sie die Datenbank-Dokumentation und unseren Erklärtext zu was Postgres ist.

Mythex · Pricing · Alles mit KI bauen · Vorlagen für Websites und Apps · Mythex im Vergleich · Glossar zum App-Bau mit KI · Kostenlose Tools für den App-Bau mit KI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)