← Усі статті

Два сервери і свідок: відмовостійкість для Totum

Як підняти Totum на двох основних серверах і маленькому свідку: перемикання бази, файли і перевірка здоров’я.

Два сервери і свідок: відмовостійкість для Totum
Зміст

Коротко

На «Хабрі» розбирають перенесення робочої системи на Totum з однієї віртуальної машини на схему з двох основних серверів і маленького свідка. Третю повноцінну машину купувати не хотіли, але кворум для сховища конфігурації без неї не зібрати. База перемикається сама, застосунок пише лише на поточному провідному вузлі, файли їдуть в один бік, а зовнішній балансувальник дивиться на перевірку здоров’я і не вимагає ручної зміни DNS.

Що сталося

Totum — платформа з розміщенням у себе для внутрішніх вебзастосунків: облік, кабінети, прикладні таблиці і своя логіка, плюс вихідні запити по HTTP. У статті це вже не стенд, а бойова система з PostgreSQL, файлами користувачів і інтеграціями. Умови були жорсткі і побутові: падіння однієї основної машини не зупиняє систему, база перемикається сама, застосунок знає, де йому можна писати, файли доступні після перемикання, DNS руками не чіпають, усе розкочується через Ansible.

Свідок майже не несе прикладне навантаження. Він потрібен, щоб у etcd був кворум. PostgreSQL ведуть через Patroni: вибір провідного і асинхронна репліка. Роль застосунку прив’язана до цього провідного. Перевірка дивиться, чи є поточний вузол основним у Patroni; якщо так — створюється ознака активного вузла, якщо ні — ознака знімається. Ідея коротка: хто тримає базу на запис, той і є єдиним живим застосунком.

Балансувальник сьомого рівня знає обидва вузли Totum, але здоров’я питає в GET /ha-health. Активний відповідає HTTP 200, пасивний — HTTP 503. Коли Patroni змінює провідного, перевірка ролі оновлює ознаку, балансувальник бачить нову картину і веде людей на інший вузол. Імена в DNS при цьому не переписують.

Файли через Patroni не їдуть. Їх синхронізують lsyncd і rsync, і лише в один бік: з активного на пасивний. Після перемикання напрямок розвертається разом із роллю. Двостороннє копіювання автор називає небезпечним: обидві машини почнуть писати одна одній і отримають конфлікти. Тому приймати зміни може лише пасивний вузол — це і є огорожа.

Окремо виплив не база, а пул PHP-FPM. Повільні вихідні виклики через curl тримали робочі процеси, нові запити чекали, і інтерфейс виглядав мертвим цілком. Тимчасовий повільний журнал із порогом 2 секунди і глибиною сліду 50 показав зависання на зовнішніх викликах, довгому опитуванні і перевірці сповіщень. Замір навколо curl розклав час: з’єднання близько 0,01 секунди, а час до першого байта — 76,4 і 15,6 секунди. Чекали не мережу до сусіда, а чужу відповідь. Пул збільшили: до 40 дітей, старт і запас по 20, стеля запасу 40. Окремий повільний запит лишився повільним, але перестав класти весь Totum.

Чому це важливо

Класична картинка відмовостійкості — три великі сервери, кластер і сховище «як у підручнику». Тут третю машину лишили маленькою і чесно назвали схему компромісом. Для внутрішньої системи, яку треба відвести з єдиної точки відмови і не роздувати рахунок, це корисніше за схему, яку немає на чому розгорнути. Межа проведена ясно: кворум є, прикладний запис один, файли не сперечаються одне з одним.

Другий урок ширший за Totum. Перемикання бази не лікує пул, який увесь пішов у чужий HTTP. Поки робочі процеси скінчилися, користувачеві байдуже, що PostgreSQL живий. Замір до першого байта відділив «повільно з’єднуємося» від «сусід довго думає», а ріст пулу локалізував шкоду, не прискоривши чужий API. Це різні лагодження, і їх легко сплутати, якщо дивитися лише на скаргу «все лежить».

На практиці

Стаття — досвід однієї установки, не універсальне креслення. Асинхронна репліка означає, що за жорсткого падіння провідного останні записи можна втратити; автор обирає автоматичне перемикання, а не синхронний запис на обидва вузли. Перш ніж копіювати числа пулу, варто зняти свій повільний журнал: 40 процесів допомогли їм, бо вузьким місцем була чужа відповідь, а не процесор.

Огорожу файлів легко зламати «зручним» двостороннім rsync. Якщо обидва вузли на хвилину вважають себе активними, копії роз’їдуться. Ознака активності повинна мати одне джерело — у них це провідний Patroni, — і перевірка здоров’я повинна дивитися на нього, а не на те, що процес просто запущений.

  1. Закладіть свідка під кворум etcd, якщо не готові купувати третій повноцінний сервер.
  2. Прив’яжіть право писати в застосунок до провідного PostgreSQL, а не до факту, що вебпроцес живий.
  3. Віддавайте балансувальнику HTTP 200 лише з активного вузла і HTTP 503 з пасивного, без ручного DNS.
  4. Синхронізуйте файли в один бік і перевертайте напрямок разом із роллю.
  5. Якщо «все повільно», зніміть слід довгих запитів і час до першого байта зовнішнього виклику до того, як збільшувати пул.

Підсумок

Схема «два сервери і свідок» відводить Totum з однієї машини, не перетворюючи третій вузол на ще одну копію застосунку. Живий запис один, файли йдуть за ним, люди приходять туди, де перевірка здоров’я зелена. Поруч виявився окремий контур: чужі довгі відповіді клали пул, і це лікувалося вимірюванням і запасом процесів, а не ще одним сервером бази.

Коментарі

Завантаження коментарів…