Blog

Probouzení databází bez mrtvých spojení

Publikované aplikace na Mythexu i jejich databáze po čase nečinnosti usínají. Když se aplikace probudila, mohla první požadavek držet 10–12 sekund, protože se pokoušela znovu použít databázová spojení, která během spánku všechna odumřela. Nyní dáváme Spring Boot aplikacím nastavení databáze, které je bezpečné i přes spánek, a agentovi říkáme, aby stavěl aplikace jakéhokoli stacku stejným způsobem. Na hostingové platformě se první požadavek po probuzení zkrátil z 12,7 sekundy na 2,3 sekundy.

Proč aplikace a databáze usínají

Publikovaná aplikace na Mythexu běží na stroji, který se po několika minutách nečinnosti pozastaví, a její databáze je bezserverový Postgres, který usne po pěti minutách nečinnosti a probudí se při dalším dotazu. To udržuje tichou aplikaci levnou: platíte za to, co databáze skutečně využila, a usínající aplikace nic nestojí za výpočetní výkon. Psali jsme o účtování té části v článku účtování databází podle skutečného využití.

Spíš je to past: oba usínají samostatně a nesouhlasí v tom, co je spojení.

Příznak: pomalá první návštěva

Většina serverových aplikací drží connection pool: hrstku otevřených databázových spojení připravených k použití, takže každý požadavek neplatí cenu otevření nového. Pro aplikaci, která je pořád zapnutá, je to správný návrh.

Tady je, co se děje při spánku:

  1. Aplikace běží s několika nečinnými spojeními v poolu.
  2. Nikdo nenavštíví. Stroj aplikace se pozastaví – zmrazený, s poolem nedotčeným.
  3. Databáze usne a zavře svůj konec všech spojení.
  4. Přijde návštěvník. Aplikace se probudí přesně tak, jak byla, pořád držíc spojení, o kterých databáze už neví.
  5. Pool předá jedno z těchto spojení. Musí zjistit, že je mrtvé – zkusit ho použít a počkat –, než se ho vzdá.

Ve Spring Boot aplikaci validace těchto mrtvých spojení blokovala první požadavek zhruba 10 sekund, než selhal s chybou „Connection is not available“. Pro návštěvníka web prostě visel a pak možná ukázal chybu.

Proč to nejvíc schytaly aplikace Springu

Spring Boot je populární Java framework a ve výchozím nastavení používá connection pool jménem HikariCP. Spring může ten pool nastavit z konfigurace, včetně toho, kolik nečinných spojení držet.

Mythex ale dává každé aplikaci její databázi jako jediné DATABASE_URL ve tvaru postgresql://user:pass@host/db. Spring tento formát nečte přímo. Aplikace Springu postavené na Mythexu si proto pool vytvářely v kódu parsováním té URL – a pool sestavený ručně ignoruje všechna nastavení spring.datasource.*. I kdyby někdo znal správná nastavení poolu, neměla by kde se projevit.

Oprava, část 1: nastavení, které Spring umí použít

Když projekt má databázi, nyní dostává také proměnné prostředí, které Spring čte nativně:

  • SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME a SPRING_DATASOURCE_PASSWORD, převedené z DATABASE_URL (s vyžadovaným SSL, pokud URL neříká jinak).
  • Nastavení poolu, která přežijí spánek:
NastaveníHodnotaProč
Minimum nečinných spojení0Mezi požadavky nic neudržovat otevřené, takže nic nezastará
Časový limit nečinnosti30 sekundNepoužívaná spojení brzy zavřít
Maximální životnost2 minutyUkončit každé spojení dřív, než zestárne
Časový limit spojení5 sekundNenechat požadavek viset dlouho, pokud databáze odpovídá pomalu

Když aplikace nedrží žádná nečinná spojení, probuzená aplikace otevře jedno čerstvé místo toho, aby se brodila mrtvými.

Pokud jsou tyto proměnné přítomné, Spring nastaví pool sám a nastavení se uplatní. Cokoli, co projekt nastavil sám, má vždy přednost; my doplňujeme jen to, co chybí. Aplikace, které nejsou Spring, tyto proměnné ignorují.

Detail, který málem nedělal nic

Spring mapuje proměnné prostředí na svá nastavení podle pravidla, které se snadno splete. Nastavení minimum-idle se musí psát jako SPRING_DATASOURCE_HIKARI_MINIMUMIDLE – pomlčky vynechané, slova spojená dohromady. Napsané jako SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, což vypadá přirozeněji, se namapuje na jiné, neexistující nastavení (minimum.idle) a je tiše ignorováno.

Takový omyl projde každou kontrolou a v produkci nic nedělá. Proto test ověřuje jak to, že hodnoty jsou nastavené, tak to, že žádná proměnná nepoužívá tvar s podtržítky.

Oprava, část 2: všechny ostatní stacky

Spring není jediný framework s poolem a nemůžeme předkonfigurovat každou knihovnu v každém jazyce. Agent Mythexu – AI, která píše vaši aplikaci – proto nyní dostává trvalou instrukci pro každý stack: publikované aplikace a jejich databáze při nečinnosti usínají, takže spojení, které se drželo otevřené, může být při dalším požadavku mrtvé. Měl by:

  • nedržet žádná nečinná databázová spojení otevřená, nebo každé před použitím ověřit,
  • jednou zopakovat požadavek při chybě spojení, a
  • používat nastavení databáze, které platforma poskytuje v prostředí, místo aby si vytvářel vlastní pool parsováním DATABASE_URL.

Poslední bod uzavírá smyčku s částí 1: aplikace postavená na poskytnutém nastavení automaticky převezme konfiguraci bezpečnou při spánku.

Výsledek

Měřeno na hostingové platformě, na které běží publikované aplikace, se první požadavek po probuzení zkrátil z 12,7 sekundy na 2,3 sekundy.

Co jsme si z toho odnesli

  • Každá vrstva, která usíná, musí souhlasit s tím, co přežije. Zmrazená aplikace a usnulá databáze udělaly každá rozumnou volbu. Dohromady se aplikace probudila s stavem, který už nebyl pravdivý.
  • Výchozí hodnoty navržené pro servery běžící pořád se nehodí na aplikace, které se škálují na nulu. Udržovat spojení teplá je dobrý nápad, dokud okolí nevychladne.
  • Dejte frameworkům data v jejich vlastním formátu. Jedna URL byla pro nás jednoduchá, ale nutila každou Spring aplikaci ručně psát pool, který ignoroval vlastní konfiguraci.
  • Ověřte, že nastavení je napsané tak, jak ho framework čte. Správná hodnota pod špatným jménem nedělá nic, a tiše.

Pokud se v Mythexu teprve orientujete v databázích, podívejte se do dokumentace k databázím a do našeho vysvětlení co je Postgres.

Mythex · Pricing · Vytvořte cokoli s AI · Šablony webů a aplikací · Mythex v porovnání · Slovník tvorby aplikací s AI · Bezplatné nástroje pro tvorbu aplikací s AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Dansk Deutsch Ελληνικά 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 简体中文 繁體中文(香港) 繁體中文(台灣)