Настройка високої доступності блокчейн-ноди
Одиночна нода — це single point of failure. Для production сервісу, який залежить від блокчейн-даних (dApp, платіжний процесор, торговий бот), downtime ноди = downtime продукту. Високої доступності (HA) — це не просто "запустити дві ноди". Це продумана архітектура з failover, health checking, і розумінням того, що саме і як може сломатися.
Типові причини недоступності ноди
Перед побудовою HA потрібно розуміти від чого захищаємось:
- Нода відстає від tip (Ethereum: пересинх після краху; Solana: slot lag > 100)
- RPC перегружен — один інстанс не справляється з нагрузкою запитів
- Оновлення клієнта — під час rolling update нода недоступна
- Hardware failure — диск, RAM, мережева карта
- Snapshot corruption — після неочікуваного відключення живлення
Архітектура: active-active за load balancer
Найпрактичніша схема для RPC нод:
Client запити
│
┌───▼───┐
│ HAProxy / Nginx │ ← health check кожні 5s
└───┬───┘
│
┌────┴────┐
▼ ▼
Node-1 Node-2 ← різні AZ / датацентри
│ │
└────┬────┘
│
Shared або
independent storage
Active-active краще активного-passive для RPC: обидві ноди приймають трафік, нагрузка розподіляється, failover миттєвий (не потрібно чекати промоції secondary).
HAProxy конфігурація для Ethereum RPC
# /etc/haproxy/haproxy.cfg
global
maxconn 50000
log stdout format raw daemon
defaults
mode http
timeout connect 5s
timeout client 60s
timeout server 60s
option http-server-close
option forwardfor
frontend ethereum_rpc
bind *:8545
bind *:8546 # WebSocket
default_backend ethereum_nodes
backend ethereum_nodes
balance leastconn
option httpchk POST / HTTP/1.1\r\nHost:\ localhost\r\nContent-Type:\ application/json\r\nContent-Length:\ 68\r\n\r\n{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}
http-check expect string '"result":false' # нода в sync якщо eth_syncing = false
server node1 10.0.1.10:8545 check inter 5s fall 2 rise 3
server node2 10.0.1.11:8545 check inter 5s fall 2 rise 3
# Sticky sessions для WebSocket (не можна переключати mid-subscription)
stick-table type ip size 100k expire 30m
stick on src
frontend ethereum_ws
bind *:8546
default_backend ethereum_ws_nodes
backend ethereum_ws_nodes
balance source # WebSocket — по source IP для sticky
server node1 10.0.1.10:8546 check inter 10s fall 2 rise 3
server node2 10.0.1.11:8546 check inter 10s fall 2 rise 3
Критичний момент для WebSocket: підписки (eth_subscribe, Solana slotSubscribe) — stateful з'єднання. При failover WebSocket клієнт повинен пересоздати підписки. У load balancer використовуємо sticky sessions за IP — клієнт завжди йде до однієї ноди поки вона жива.
Health check: що перевіряти
Стандартний HTTP health check (status 200) — недостатній. Нода може відповідати на HTTP, але при цьому бути на 1000 блоків позаду tip. Правильна перевірка:
#!/bin/bash
# /etc/haproxy/scripts/check_eth_node.sh
# Повертає 0 якщо нода здорова, 1 якщо ні
NODE_URL="http://localhost:8545"
# 1. Перевіряємо що нода не в процесі синхронізації
SYNCING=$(curl -sf -X POST "$NODE_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_syncing","params":[],"id":1}' | \
jq -r '.result')
if [ "$SYNCING" != "false" ]; then
exit 1
fi
# 2. Перевіряємо що блок не старше 3 хвилин (180 секунд)
BLOCK_HEX=$(curl -sf -X POST "$NODE_URL" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["latest",false],"id":1}' | \
jq -r '.result.timestamp')
BLOCK_TIME=$((16#${BLOCK_HEX#0x}))
NOW=$(date +%s)
AGE=$((NOW - BLOCK_TIME))
if [ $AGE -gt 180 ]; then
exit 1
fi
exit 0
Аналогічна логіка для Solana — перевіряємо getSlot і порівнюємо з getEpochInfo, допуск в 50–100 слотів.
Rolling update без downtime
Оновлення клієнта — найчастіша причина планових даунтаймів. З HA це вирішується:
#!/bin/bash
# rolling_update.sh
# Крок 1: виводимо node1 з rotation
haproxy -sf $(cat /var/run/haproxy.pid) -f /etc/haproxy/haproxy_node2_only.cfg
# Крок 2: чекаємо drain існуючих з'єднань
sleep 30
# Крок 3: оновлюємо node1
ssh node1 "systemctl stop geth && apt upgrade -y ethereum && systemctl start geth"
# Крок 4: чекаємо sync node1
while ! /etc/haproxy/scripts/check_eth_node.sh node1; do
echo "Waiting for node1 to sync..."
sleep 30
done
# Крок 5: повертаємо node1, оновлюємо node2
haproxy -sf $(cat /var/run/haproxy.pid) -f /etc/haproxy/haproxy.cfg
sleep 30
ssh node2 "systemctl stop geth && apt upgrade -y ethereum && systemctl start geth"
Моніторинг і алерти
Prometheus + Grafana — стандарт. Ключові метрики:
| Метрика | Поріг алерту | Критичність |
|---|---|---|
eth_block_age_seconds |
> 120s | Critical |
haproxy_backend_active_servers |
< 1 | Critical |
haproxy_backend_response_time_ms |
> 2000ms | Warning |
node_disk_io_time_percent |
> 80% | Warning |
node_memory_available_bytes |
< 10% | Warning |
Алерти — в PagerDuty або Telegram. Для backend_active_servers < 1 (всі ноди впали) — будити дежурного немедленно.
Що входить в роботу
- Розгортання другої ноди в окремій AZ/датацентрі
- Настройка HAProxy або Nginx з розумними health checks
- Скрипти rolling update для оновлень без downtime
- Prometheus метрики, Grafana дашборд, алерти
- Документація процедур failover і відновлення







