Блог

Пробудження баз даних без мертвих з'єднань

Опубліковані застосунки на Mythex і їхні бази даних засинають, коли ними ніхто не користується. Коли застосунок прокидався, він міг тримати перший запит 10–12 секунд, бо намагався повторно використати з'єднання з базою, які померли, поки все спало. Тепер ми даємо застосункам Spring Boot налаштування бази, безпечні після сну, і вказуємо агенту будувати застосунки будь-якого стеку так само. На хостинговій платформі перший запит після пробудження скоротився з 12,7 до 2,3 секунди.

Чому застосунки і бази засинають

Опублікований застосунок Mythex працює на машині, яка призупиняється після кількох хвилин простою, а його база даних це серверлес-Postgres, що засинає після п'яти хвилин простою й прокидається з наступним запитом. Саме це утримує тихий застосунок дешевим: ви платите за те, що база справді використала, а застосунок, що спить, не витрачає ресурсів на обчислення. Ми писали про білінг з цього боку в оплаті баз даних за фактичним використанням.

Пастка в тому, що вони засинають окремо і не згодні щодо того, що таке з'єднання.

Симптом: повільний перший візит

Більшість серверних застосунків тримають пул з'єднань: кілька відкритих з'єднань із базою, готових заздалегідь, щоб кожен запит не платив за відкриття нового. Це правильний дизайн для застосунку, який працює завжди.

Ось що відбувається зі сном:

  1. Застосунок працює, у його пулі є кілька неактивних з'єднань.
  2. Ніхто не заходить. Машина застосунку призупиняється, заморожена разом з пулом.
  3. База даних засинає і закриває свій кінець кожного з'єднання.
  4. Приходить відвідувач. Застосунок прокидається точно таким, яким був, і досі тримає з'єднання, про які база вже не знає.
  5. Пул видає одне з таких з'єднань. Він має з'ясувати, що воно мертве, спробувавши його і почекавши, перш ніж відмовитися.

У застосунку Spring Boot перевірка цих мертвих з'єднань блокувала перший запит приблизно на 10 секунд, перш ніж він завершувався помилкою «Connection is not available». Для відвідувача сайт просто зависав, а потім, може, показував помилку.

Чому Spring-застосункам було найгірше

Spring Boot це популярний Java-фреймворк, і за замовчуванням він використовує пул з'єднань HikariCP. Spring може налаштувати цей пул через параметри, зокрема скільки неактивних з'єднань тримати.

Але Mythex дає кожному застосунку його базу як одну змінну DATABASE_URL у форматі postgresql://user:pass@host/db. Spring не може прочитати цей формат напряму. Тому Spring-застосунки на Mythex створювали власний пул у коді, розбираючи цей URL, а пул, створений вручну, ігнорує всі налаштування Spring spring.datasource.*. Навіть якщо хтось знав правильні налаштування пулу, не було місця, де вони б подіяли.

Виправлення, частина 1: налаштування, які Spring може використати

Коли в проєкту є база, тепер ми також задаємо змінні середовища, які Spring читає нативно:

  • SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME і SPRING_DATASOURCE_PASSWORD, перетворені з DATABASE_URL (з вимогою SSL, якщо URL не каже інакше).
  • Налаштування пулу, що переживають сон:
НалаштуванняЗначенняЧому
Мінімум неактивних з'єднань0Між запитами нічого не тримати відкритим, тож нема чого застаріти
Тайм-аут простою30 секундШвидко закривати невикористовувані з'єднання
Максимальний термін життя2 хвилиниВивести з обігу кожне з'єднання до того, як воно постаріє
Тайм-аут з'єднання5 секундНе тримати запит довго, якщо база повільно відповідає

Коли неактивних з'єднань не тримається, застосунок, що прокинувся, відкриває одне нове з'єднання замість того, щоб продиратися крізь мертві.

Коли ці змінні присутні, Spring сам налаштовує пул, і налаштування працюють. Усе, що проєкт налаштував сам, завжди має перевагу; ми заповнюємо лише те, чого бракує. Не-Spring застосунки ігнорують ці змінні.

Деталь, що майже нічого не зробила

Spring зіставляє змінні середовища з налаштуваннями за правилом, яке легко порушити. Параметр minimum-idle треба писати як SPRING_DATASOURCE_HIKARI_MINIMUMIDLE: крапки й дефіси прибрано, слова злиті. Якщо написати SPRING_DATASOURCE_HIKARI_MINIMUM_IDLE, що виглядає природніше, він зіставляється з іншим, неіснуючим параметром (minimum.idle) і тихо ігнорується.

Така помилка проходить усі перевірки і нічого не робить у продакшені. Тому тест перевіряє і те, що значення задані, і те, що жодна змінна не використовує форму з підкресленнями.

Виправлення, частина 2: кожен інший стек

Spring не єдиний фреймворк із пулом, а ми не можемо заздалегідь налаштувати кожну бібліотеку на кожній мові. Тому агент Mythex, що пише ваш застосунок, тепер отримує постійну інструкцію для будь-якого стеку: опубліковані застосунки та їхні бази засинають, коли простоюють, тож з'єднання, відкрите раніше, може бути мертвим під час наступного запиту. Агент має:

  • не тримати неактивних з'єднань із базою відкритими або перевіряти кожне перед використанням,
  • один раз повторити запит у разі помилки з'єднання,
  • використовувати налаштування бази, які платформа надає в середовищі, а не створювати власний пул, розбираючи DATABASE_URL.

Останній пункт замикає коло з частиною 1: застосунок, побудований на наданих налаштуваннях, автоматично отримує конфігурацію, безпечну для сну.

Результат

Вимірявши на хостинговій платформі, де ми запускаємо опубліковані застосунки, ми отримали: перший запит після пробудження скоротився з 12,7 секунди до 2,3 секунди.

Що ми з цього взяли

  • Кожен шар, що засинає, має погодитися щодо того, що зберігається. Заморожений застосунок і спляча база кожен зробили розумний вибір. Разом застосунок прокинувся з станом, який уже не був правдивим.
  • Значення за замовчуванням, розраховані на серверні машини, що працюють завжди, не пасують застосункам, які масштабуються до нуля. Тримати з'єднання теплими добра ідея, доки все навколо не остигло.
  • Давайте фреймворкам їхні дані у їхньому форматі. Один URL був простим для нас, але змусив кожен Spring-застосунок вручну писати пул, який ігнорував власну конфігурацію.
  • Перевіряйте, що налаштування написане так, як його читає фреймворк. Правильне значення під неправильною назвою нічого не робить, тихо.

Якщо ви тільки знайомитеся з тим, як працюють бази даних на Mythex, дивіться документацію з баз даних і наше пояснення що таке Postgres.

Mythex · Pricing · Створюйте що завгодно з ШІ · Шаблони сайтів і застосунків · Порівняння Mythex · Глосарій створення застосунків за допомогою ШІ · Безкоштовні інструменти для створення застосунків за допомогою ШІ · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština 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 简体中文 繁體中文(香港) 繁體中文(台灣)