Настройка высокодоступности блокчейн-ноды
Одиночная нода — это 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 requests
│
┌───▼───┐
│ HAProxy / Nginx │ ← health check каждые 5s
└───┬───┘
│
┌────┴────┐
▼ ▼
Node-1 Node-2 ← разные AZ / датацентры
│ │
└────┬────┘
│
Shared или
independent storage
Active-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 и восстановления







