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

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

Що таке RPC-вузол та його роль

RPC-вузол (Remote Procedure Call node) — це екземпляр клієнта Agave (колишній agave-validator), запущений без ключа валідатора та без голосування. Його єдина функція — підтримувати актуальний стан мережі та обслуговувати запити через HTTP або WebSocket.

Типовий набір операцій, які виконує RPC-вузол:

  • підключення до gossip-мережі та отримання блоків від валідаторів;
  • застосування транзакцій і підтримка актуального стану рахунків (accounts DB);
  • відповіді на JSON-RPC-запити: читання стану, відправка транзакцій, підписка на події.

Клієнт: Agave. Кластер: mainnet-beta / testnet. ОС: Ubuntu 24.04 LTS. Дата перевірки актуальності команд: червень 2025 — перевірте відповідність вашій версії Agave командою agave-validator --version.

Базовий запуск RPC-вузла відрізняється від валідатора відсутністю прапорців голосування:

agave-validator --ledger /mnt/ledger --rpc-port 8899 --rpc-bind-address 0.0.0.0 --dynamic-port-range 8000-8020 --entrypoint entrypoint.mainnet-beta.solana.com:8001 --known-validator 7Np41oeYjPp3sU7bV2HLiFQV4EmTCR9YwXJn5h1XeCBJ --known-validator GdnSyH3YtwcxFvQrVVJMm1JhTS4QYX2uFNLRLrTz1UwV --known-validator DE1bawNcRJB9rVm3LsZc3XxH6zLhgUuTJzWftXwpG5fP --no-voting --full-rpc-api

Прапорець --no-voting виключає вузол із консенсусу. --full-rpc-api дозволяє викликати всі методи, включно з адміністративними (getProgramAccounts з фільтрами тощо).

Різниця між валідатором та RPC-вузлом

Обидва типи вузлів запускають однаковий бінарний файл і підтримують ідентичну локальну базу даних (AccountsDb, Bank). Різниця полягає в ролі в мережі та ресурсному профілі.

Параметр Валідатор RPC-вузол
Голосування Так, кожні ~400 мс Ні
Участь у консенсусі Повна (лідерство, голосування, форк-вибір) Тільки споживання даних
Навантаження на мережу (вихідне) Високе (голоси, транзакції, shred-розповсюдження) Помірне (gossip, запити блоків)
Навантаження на CPU (консенсус) Високе (верифікація підписів, PoH) Нижче, але значне при важких RPC-запитах
Навантаження на диск (запис) Високе (append-only ledger + AccountsDb) Помірне (те саме читання, але без запису голосів)
Публічний API Зазвичай вимкнений або обмежений Основна функція

Ключовий наслідок: RPC-вузол не потребує ключа валідатора, не несе ризику штрафів (slash) і може бути перезапущений без впливу на консенсус. Але він споживає стільки ж дискового простору та RAM, оскільки зберігає повний стан мережі.

Навантаження на RPC: типові обсяги запитів

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

Класифікація методів за вартістю

Усі JSON-RPC методи Solana суттєво відрізняються за ресурсами, які вони споживають на стороні вузла:

  • Легкі (мікросекунди, переважно CPU): getHealth, getSlot, getBlockHeight, getEpochInfo, getClusterNodes. Читання змінних у памʼяті, без звернень до AccountsDb.
  • Середні (мілісекунди, RAM + диск): getAccountInfo, getBalance, getTransaction. Пошук одного рахунку або транзакції в AccountsDb або ledger.
  • Важкі (секунди, інтенсивний RAM + CPU + диск): getProgramAccounts, getSignaturesForAddress, getBlocksWithLimit, getBlock (з повними транзакціями). Сканування великих обсягів даних, десеріалізація сотень або тисяч обʼєктів.
  • Спеціальні (залежить від параметрів): simulateTransaction — виконує транзакцію в пісочниці, споживає CPU і RAM пропорційно складності транзакції.

Один виклик getProgramAccounts без фільтрів по великому програмі (наприклад, Token Program) може завантажити в памʼять мільйони рахунків. Це найчастіша причина деградації RPC-вузла.

Типові патерни навантаження

Для внутрішнього RPC (один або кілька власних сервісів) навантаження зазвичай становить від одиниць до десятків RPS із переважанням легких і середніх методів. Для публічного RPC або інфраструктури, що обслуговує сторонні dApp, навантаження може сягати сотень або тисяч RPS із значною часткою важких запитів.

Щоб виміряти реальний профіль навантаження на вашому вузлі, увімкніть логування RPC-запитів та проаналізуйте журнали:

agave-validator --log-level info --rpc-log-enable-methods getProgramAccounts,getSignaturesForAddress,simulateTransaction ...

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

Горизонтальне масштабування: кілька RPC за балансувальником

Вертикальне масштабування одного RPC-вузла має жорсткі обмеження: RAM, кількість ядер CPU та швидкість диску. Коли один вузол досягає межі, єдиний робочий підхід — горизонтальне масштабування: запуск кількох RPC-вузлів за балансувальником навантаження.

Архітектура

Типова схема:

  1. Кілька незалежних RPC-вузлів (кожен зі своїм ledger), підключених до мережі через однакові entrypoints.
  2. Балансувальник (HAProxy, Nginx, Envoy) перед вузлами, який розподіляє вхідні HTTP та WebSocket-запити.
  3. Опціонально — рівень кешування перед балансувальником.

Кожен RPC-вузол синхронізується з мережею незалежно. Вони не обмінюються станом між собою. Балансувальник не знає про внутрішній стан вузлів — він просто розподіляє запити за алгоритмом (round-robin, least-connections тощо).

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

Середовище: Ubuntu 24.04 LTS, HAProxy 2.4+. Передумови: три RPC-вузли на 127.0.0.1:8899, 127.0.0.1:8900, 127.0.0.1:8901. Очікуваний результат: HTTP-запити розподіляються рівномірно, WebSocket-зʼєднання тримаються на одному бекенді.

frontend solana-rpc
  bind *:8999
  mode http
  option httplog
  timeout client 30s
  default_backend rpc-nodes

backend rpc-nodes
  mode http
  balance leastconn
  option httpchk GET /health
  http-check expect status 200
  timeout connect 5s
  timeout server 30s
  server rpc1 127.0.0.1:8899 check
  server rpc2 127.0.0.1:8900 check
  server rpc3 127.0.0.1:8901 check

Перевірка: curl http://localhost:8999/health — має повернути ok. Ризики: якщо один вузол відстає за слотом, балансувальник все одно направлятиме туди запити. Додайте перевірку слота через зовнішній скрипт, якщо це критично.

Обмеження підходу

  • Кожен вузол споживає повний обсяг RAM і диска незалежно. Три RPC-вузли — це потроєння витрат на памʼять і накопичувачі.
  • WebSocket-підписки привʼязані до конкретного бекенда. Якщо цей бекенд перезапускається, клієнт втрачає підписку і має перепідключатися.
  • Запити sendTransaction можуть бути відправлені на вузол, який тимчасово відстає, що збільшує затримку підтвердження.

Кешування та обмеження запитів

Кешування та rate limiting — два основні інструменти для зниження навантаження на RPC-вузли без додавання нових інстансів.

Кешування

Не всі RPC-відповіді можна кешувати безпечно. Критерій: дані є кешованими, якщо вони незмінні протягом певного часу і не залежать від стану конкретного користувача.

  • Можна кешувати: getSlot, getBlockHeight, getEpochInfo, getClusterNodes, getGenesisHash — ці дані змінюються повільно (слот оновлюється ~400 мс, але затримка в 100–200 мс прийнятна для більшості клієнтів). getAccountInfo для рахунків, які рідко змінюються (програми, mint-рахунки).
  • Не можна кешувати: sendTransaction, simulateTransaction (залежать від поточного стану та вхідних даних), getLatestBlockhash (використовується для транзакцій, кешування може спричинити невикористані blockhash).

Практична реалізація: розмістіть кешуючий проксі (наприклад, Nginx з proxy_cache або спеціалізований сервіс) перед балансувальником. Налаштуйте TTL для легких методів на 200–500 мс, для getAccountInfo — на 1–5 с (за потреби).

Ризик: застарілий кешований getAccountInfo може призвести до відправки транзакції з неправильним станом рахунку. Завжди перевіряйте, чи ваш клієнт коректно обробляє помилку блокування рахунку (account in use) або невідповідність стану.

Обмеження запитів (rate limiting)

Rate limiting захищає RPC-вузли від випадкового або навмисного перевантаження. Реалізується на рівні балансувальника або окремим компонентом.

Рекомендовані підходи:

  • За IP-адресою: базовий рівень захисту. Наприклад, 100 RPS на IP для легких методів, 10 RPS для важких. Обмеження: не працює, якщо кілька клієнтів знаходяться за одним NAT.
  • За API-ключем: якщо ви надаєте RPC як сервіс, привʼяжіть ліміти до ключа. Це точніше, але вимагає додаткової логіки авторизації.
  • За методом: окремі ліміти для getProgramAccounts та simulateTransaction, оскільки саме вони генерують пікове навантаження.

Приклад обмеження в HAProxy:

backend rpc-nodes
  stick-table type ip size 100k expire 30s store http_req_rate(1s)
  http-request track-sc0 src
  http-request deny deny_status 429 if { sc_http_req_rate(0) gt 100 }

Очікуваний результат: клієнти, що перевищують 100 RPS, отримують HTTP 429. Перевірка: for i in $(seq 1 150); do curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8999/health; done — після ~100 успішних відповідей почнуть зʼявлятися 429.

Моніторинг навантаження RPC

Без моніторингу масштабування та обмеження запитів — це сліпі дії. Agave експортує метрики у форматі Prometheus, які дозволяють побудувати повну картину навантаження.

Увімкнення метрик

Середовище: Agave, будь-який кластер. Передумови: встановлений Prometheus. Додайте прапорці до запуску вузла:

--metrics-config '{"url":"0.0.0.0:8898","rate_limited":false}'

Очікуваний результат: метрики доступні за адресою http://<ip>:8898/metrics. Перевірка: curl http://localhost:8898/metrics | head -20.

Ризик: без обмеження доступу до порту 8898 будь-хто зможе зчитати метрики. Обмежте доступ firewall-ом або привʼяжіть до localhost.

Ключові метрики для RPC

  • solana_rpc_request_count — загальна кількість оброблених запитів. Розбивайте за міткою method для визначення найпопулярніших методів.
  • solana_rpc_request_duration_seconds — гістограма часу обробки. Зростання p99 для конкретного методу сигналізує про перевантаження.
  • solana_rpc_request_active_count — кількість запитів, що обробляються зараз. Різкі сплески вказують на проблеми.
  • solana_bank_processed_slots_total — поточний слот вузла. Якщо цей лічильник зупинився або відстає від інших вузлів — вузол деградував.
  • solana_accounts_db_bytes — обсяг AccountsDb у байтах. Росте постійно, але різкі стрибки можуть вказувати на аномальну активність.

Рекомендовані алерти

  • Різниця слотів між RPC-вузлами у пулі перевищує 10 — сигнал про відставання одного з інстансів.
  • p99 затримка getAccountInfo перевищує 500 мс протягом 2 хвилин — вузол не встигає обробляти навантаження.
  • Кількість активних запитів перевищує 200 — наближається межа паралелізму.
  • HTTP 429 перевищує 5% від загальних відповідей — ліміти занадто жорсткі або є абузер.

Для зручного перегляду метрик налаштуйте дашборд у Grafana з панелями для кожної ключової метрики, розбитими за методами RPC та за інстансами. Це дозволить швидко візуально визначити, який саме метод або вузол створює проблему.

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

Джерела