Розподілена архітектура валідатора Solana — це не розкіш, а операційна необхідність для інфраструктури, яка обслуговує RPC-клієнтів, стрімінг-підписки або високодоступні сервіси. Один вузол дає єдину точку відмови. Нижче — практична схема переходу до кількох вузлів із конкретними конфігураціями, обмеженнями та перевірками.

Операційні вимоги для «Розподілена архітектура: кілька вузлів, балансування, географія» перевірено 2 серпня 2026 року. Для production використовуйте тільки реліз Agave, рекомендований для конкретного кластера, і звіряйте параметри з agave-validator --help . Офіційні вимоги Anza на цю дату орієнтують операторів на Ubuntu 24.04, щонайменше 12 ядер/24 потоки, 256 ГБ RAM, окремі швидкі NVMe та симетричний канал від 2 Гбіт/с; це рекомендації, а не гарантія достатньої продуктивності.

Коли одному вузлу недостатньо

Один валідатор Solana (агрегатор) здатен обробляти значний обсяг трафіку, але є сценарії, де його ресурсів стає недостатньо:

  • RPC-навантаження. Публічний або приватний RPC-вузол під час пікової активності мережі виходить за межі доступного йому CPU або мережевого пропускання. Запити починають таймаутити, а черга gossip-протоколу зростає.
  • Стрімінг-підписки (WebSocket). Кожна активна підписка на accountSubscribe або logsSubscribe утримує відкрите з'єднання та споживає ресурси. Десятки тисяч підписок на одному вузлі стабільно деградують його продуктивність.
  • Вимоги до доступності (SLA). Якщо інфраструктура обслуговує сторонні сервіси з contractual uptime, планові перезапуски для оновлення або непланові перезавантаження ядра стають неприпустимими.
  • Географічна латентність. Клієнти з різних регіонів отримують неприйнятно високий ping до єдиного дата-центру, що впливає на таймаути їхніх запитів.

Критерій переходу до кількох вузлів простий: якщо ви фіксуєте стабільне перевищення 70–80% використання CPU під час пікових слотів, або якщо черга tpu регулярно перевищує 200 пакетів — час розширювати архітектуру.

Архітектура з кількома валідаторами

У контексті Solana «кілька вузлів» означає кілька незалежних екземплярів клієнта agave-validator, кожен зі своїм набором identity-ключів. Важливо розрізняти дві моделі:

Модель A: Кілька валідаторів під одним identity. Технічно неможлива в Solana. Кожен екземпляр валідатора має унільний identity-ключ, і мережа не дозволяє двом вузлам з однаковим identity голосувати одночасно — це сприймається як дублювання й призводить до slash-подібних наслідків (втрата делегованих стейків через епоху без голосів).

Модель B: Незалежні валідатори з єдиним входом. Кожен вузол має власний identity-ключ і власну ставку. Зовнішні клієнти підключаються до них через спільний балансувальник або DNS-пул. Це єдина коректна схема.

Типова топологія:

  • Вузол 1 (Validator-A). Основний валідатор, повний стек: gossip, RPC, TPU.
  • Вузол 2 (Validator-B). Другий валідатор, повний стек, інший identity-ключ, інший дата-центр.
  • Вузол 3 (RPC-only). Не голосує, не має stake. Працює виключно як RPC-ендпоінт, підписується на gossip-мережу, але не бере участі в консенсусі. Корисний для зняття навантаження з голосуючих вузлів.

RPC-only вузол конфігурується прапорцями --no-voting та відсутністю --identity з голосуючим ключем. Він синхронізує леджер через gossip, але не формує блоки й не голосує.

Балансування навантаження між вузлами

Балансування в інфраструктурі Solana відрізняється від типового HTTP-балансування. Запити до RPC — це JSON-RPC над HTTP/WebSocket, тому на рівні L4/L7 працюють стандартні інструменти. Але є нюанси:

Стратегії розподілу

  • Round-robin (L4). Найпростіший варіант через HAProxy або Nginx у режимі stream. Підходить для stateless JSON-RPC запитів (getBalance, getAccountInfo). Має сенс, коли всі вузли однаково потужні.
  • Least connections (L4/L7). Віддає запит вузлу з найменшою кількістю активних з'єднань. Критично важливий для WebSocket-стрімінгу, де кожне з'єднання триває хвилинами або годинами.
  • Розділення за типом трафіку. JSON-RPC запити йдуть на RPC-only вузли, а голосування та gossip залишаються на повних валідаторах. Це найбільш правильна архітектурна модель.

Приклад конфігурації HAProxy для JSON-RPC

Середовище: HAProxy 2.8, Ubuntu 24.04 LTS, два RPC-вузли Solana. Перевірено: січень 2025.

Передумови: обидва вузли прослуховують порт 8899, HAProxy встановлено на окремій машині або на одному з вузлів (менш бажано).

Ризики: HAProxy стає єдиною точкою відмови для RPC. Рекомендується пара HAProxy з VRRP (keepalived).

Очікуваний результат: JSON-RPC запити розподіляються між вузлами за алгоритмом leastconn.

Конфігураційний фрагмент (frontend + backend):
frontend solana_rpc
bind *:8899
mode tcp
default_backend solana_rpc_nodes

backend solana_rpc_nodes
mode tcp
balance leastconn
server node1 10.0.1.10:8899 check
server node2 10.0.2.10:8899 check

Перевірка: виконайте curl http://haproxy-ip:8899 -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"getHealth"}' кілька разів і перевірте логи кожного вузла (journalctl -u solana -f) — запити мають чергуватися.

Відкат: видаліть конфігураційний блок з /etc/haproxy/haproxy.cfg та виконайте systemctl restart haproxy. Клієнти, що підключались безпосередньо до вузлів, продовжать працювати.

Специфіка WebSocket-балансування

WebSocket-з'єднання в Solana RPC тримаються довго. Стандартний health-check (HTTP GET до /) не завжди відображає реальну здатність вузла приймати нові підписки. Рекомендується додати моніторинг кількості активних WebSocket-з'єднань на кожному вузлі та динамічно зменшувати вагу вузла в HAProxy при перевищенні порогу.

Географічне розподілення: плюси та мінуси

Розміщення вузлів у різних дата-центрах або регіонах — це компроміс між доступністю та консенсусною ефективністю.

Переваги

  • Толерантність до відмов дата-центру. Якщо один DC виходить з ладу (блекаут, пожежа, масова апаратна відмова), другий вузол продовжує голосувати й обслуговувати клієнтів.
  • Зниження латентності для кінцевих клієнтів. Європейські клієнти підключаються до європейського вузла, азійські — до азійського. Це особливо помітно для WebSocket-підписок, де кожен пакет має значення.
  • Захист від регіональних обмежень. Якщо провайдер або юрисдикція раптово блокує трафік, другий регіон продовжує працювати.

Недоліки та обмеження

  • Латентність між вузлами та лідером. Solana має швидкий консенсус (близько 400 мс на слот). Якщо ваш валідатор географічно далеко від поточного лідера, він отримує пізніше пропозиції блоків, що знижує ефективність голосування та може призвести до пропущених слотів (skip rate).
  • Складність синхронізації. При додаванні нового вузла в іншому регіоні початкова синхронізація (snapshot + ledger) може зайняти значний час через пропускну здатність між регіонами.
  • Подвоєння інфраструктурних витрат. Кожен повний валідатор вимагає окремого сервера відповідної специфікації, окремого диску, окремої мережевої інфраструктури.
  • Складність моніторингу. Потрібна централізована система (Prometheus + Grafana або аналоги), що агрегує метрики з усіх регіонів з урахуванням власної латентності збору.

Практична рекомендація: для голосуючих валідаторів географічне розподілення має бути обмежене. Оптимально — два дата-центри в межах одного регіону (наприклад, два різні DC у Франкфурті), де мережева латентність між ними не перевищує 2–3 мс. Для RPC-only вузлів географія може бути ширшою, оскільки вони не беруть участі в консенсусі.

Управління конфігурацією кількох вузлів

Кілька вузлів із ручним управлінням конфігураціями — це гарантована помилка. Різниця в одному прапорці призводить до непередбачуваної поведінки, яку важко діагностувати.

Інструменти

  • Ansible. Найпоширеніший варіант для інфраструктури Solana. Playbook визначає версію бінарника, список прапорців запуску, параметри systemd-юніта, конфігурацію моніторингу. Застосовується до всіх вузлів однаково, змінні різняться лише для identity-ключів та IP-адрес.
  • systemd drop-in заміни. Замість прямого редагування /etc/systemd/system/solana.service використовуйте /etc/systemd/system/solana.service.d/override.conf. Це дозволяє тримати базовий юніт незмінним і перевизначати лише специфічні параметри.

Критичні параметри, що мають бути ідентичними

  • Версія клієнта. Усі вузли мають працювати на одній версії agave-validator. Різні версії в межах одного кластера можуть призвести до неузгодженості леджера.
  • Прапорці gossip та TPU. --gossip-port, --tpu-port (якщо перевизначаються) мають бути консистентними з мережевою конфігурацією.
  • Параметри ledger. --ledger, --accounts, --snapshot-interval-slots — різні значення ускладнюють міграцію та відновлення.
  • Обмеження RPC. Якщо вузли обслуговують спільних клієнтів, прапорці --rpc-max-request-body-size, --rpc-pubsub-max-subscriptions мають бути узгоджені, інакше клієнти отримуватимуть різну поведінку залежно від того, на який вузол потрапили.

Параметри, що мають відрізнятися

  • Identity-ключі. Кожен валідатор має унільний keypair.
  • IP-адреси та порти. Вузли в одному DC можуть використовувати однакові порти, але різні IP. Вузли в різних DC — різні зовнішні IP.
  • Назви юнітів (опціонально). Для зручності логування: agave-validator-a.service, agave-validator-b.service.

Кейс: міграція від одного до кількох вузлів

Сценарій: є один працюючий валідатор (Validator-A) у DC-1. Потрібно додати другий валідатор (Validator-B) у DC-2 без простою першого.

Крок 1. Підготовка інфраструктури Validator-B

Сервер у DC-2 має відповідати мінімальним вимогам для валідатора Solana (перевірте актуальні специфікації в офіційній документації на момент виконання). ОС, налаштування файлової системи, мережеві параметри — за стандартною процедурою підготовки.

Крок 2. Генерація identity-ключів

Середовище: будь-яка машина з встановленим solana-cli тієї ж версії, що й валідатор.

Команда:

solana-keygen new -o /path/to/validator-b-identity.json

Увага: ніколи не копіюйте identity-keypair з Validator-A на Validator-B. Це призведе до дублювання identity в мережі та ефективного виключення обох вузлів з консенсусу.

Резервний шлях: якщо випадково скопіювали ключ — негайно зупиніть один із вузлів (systemctl stop agave-validator) і згенеруйте новий keypair для нього.

Крок 3. Початкова синхронізація

Найшвидший спосіб — завантажити останній snapshot з Validator-A та передати його на Validator-B.

На Validator-A:

solana-ledger-tool create-snapshot --ledger /mnt/ledger <slot> /tmp/snapshot.tar.zst</slot>

Де <slot> — останній повний слот (можна отримати через solana slot або з логів).

Передача: rsync -avz --progress /tmp/snapshot.tar.zst user@validator-b:/mnt/ledger/

На Validator-B: розпакувати snapshot та запустити валідатор. Він підхопить леджер з точки snapshot і продовжить синхронізацію через gossip.

Перевірка: solana slot на обох вузлах має показувати наближені значення (різниця не більше 10–20 слотів під час активної синхронізації, 0 після повної).

Крок 4. Делегування стейку на Validator-B

Новий валідатор без stake не голосує ефективно. Делегуйте SOL на identity-адресу Validator-B через гаманець або інструмент stake-делегування. Перевірте, що stake активний у поточній епохі: solana show-stake <stake-account-address></stake-account-address>.

Крок 5. Налаштування балансування

Після того як Validator-B повністю синхронізовано і голосує, додайте його до балансувальника навантаження перед RPC-клієнтами. Спочатку в режимі backup або з низькою вагою, щоб переконатися в стабільності, потім — як повноцінний вузол.

Крок 6. Верифікація

  • Обидва вузли показують "ok" на getHealth.
  • Обидва вузли мають skip rate нижче 5% (перевіряється через solana validator-info або зовнішні дашборди).
  • Балансувальник розподіляє запити між вузлами (перевіряється логами).
  • Моніторинг фіксує метрики з обох вузлів.

Відкат: якщо Validator-B показує нестабільність, видаліть його з балансувальника, зупиніть юніт (systemctl stop agave-validator-b) та залишіть Validator-A як єдиний вузол. Стейк на Validator-B просто не голосуватиме, але не згориться — Solana наразі не має механізму slashing за простої.

Джерела