Концепт простого Load-balancer'a/Failover'a IP сервісів

Концепт простого Load-balancer'a/Failover'a IP сервісів

У процесі вирішення одного технічного завдання народилася ідея універсального способу розподілу навантаження на безліч машин з теоретично будь-якими сервісами, до яких можна звернутися за IP.


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

Отже, в коротці:

1. У nsswitch.conf для hosts прописуємо свою бібліотеку ДО files і dns. Так щоб у/etc/hosts і в DNS система дивилася тільки якщо наша бібліотека повернула NSS_STATUS_UNAVAIL.

2. Робимо свою бібліотеку всього з однією функцією int gethostbyname_r (...) (подробиці як реалізувати дивимося тут: www.gnu.org/s/hello/manual/libc/Name-Service-Switch.html#Name-Service-Switch). Функція дивиться чи немає запитаного імені в shared memory, якщо є - повертає звідти ж IP адресу і збільшує в shared memory лічильник використання цього імені на 1. Якщо ж у shared memory такого імені немає - повертає NSS_STATUS_UNAVAIL.

3. Якщо бібліотека повернула NSS_STATUS_UNAVAIL - система продовжує resolve імені в IP далі штатним чином (/etc/hosts, DNS).

4. Будь-якою мовою, здатною відкрити multicast socket і працювати з shared memory і named socket пишеться невеликий сервіс, який:

4.1 читає свій конфіг (початкова конфігурація) з інформацією про сервіси, передає його в мультикаст групу з позначкою «initial» і кладе в shared memory.

4.2 Все що приходить від інших членів мультикаст групи - довантажує в shared memory (або видаляє, є прийшло видалення). Якщо прийшло з позначкою «initial» - надіслати у відповідь відомі зміни щодо початкової конфігурації.

4.3 Слухає якісь команди через named socket, як наслідок додаючи/видаляючи/переставляючи щось з shared memory і дублюючи це в мультикаст групу.

4.4 Опціонально: після досягнення лічильниками в shared memory якихось значень видаляє звідти хост, дублює команду в мультикаст групу.

5. Всі, кому треба користуватися якимось сервісом, підключаються до нього по імені - бібліотека віддасть його з shared memory моментально.

Так як ми по суті справи перехоплюємо на себе стандартну функцію системи gethostbyname (), а її по ідеї використовує все, що працює за IP протоколом і згідно використовувати ім'я хосту (а не тільки IP безпосередньо) - то без будь-яких додаткових змін з цією схемою будуть працювати більшість клієнтських додатків. Якісь проблеми можуть виникнути з клієнтами які кешують проресовновлений IP (наприклад web-browser-и), втім, іноді це навіть плюс - не порветься сесія.

Таким чином отримуємо якийсь скелет, який можна підлаштувати під все що завгодно і легко керувати навантаженням і доступністю сервісів (і/або розкидати навантаження між ними) просто кидаючи команди в named socket. Це можна робити розумними скриптами/системою моніторингу/web-інтерфейсом, тупо'cat'якогось файлу з командами в named socket за cron'y і так далі.

Крім того, оскільки nss-бібліотека сама по собі буде дуже примітивна, маленька і тупа - це буде працювати дуже швидко і надійно (досить складно наробити серйозних помилок в настільки примітивному шматочку коду). Правда ніщо не заважає накосячити в керуючому сервісі або в тому, що до нього звертається...

Що думаєте?

Image