Масштабирование блокчейн-инфраструктуры: от ноды до WebSocket

Масштабирование блокчейн-инфраструктуры: от ноды до WebSocket Инфраструктура, которая нормально работала при 100 пользователях, начинает сыпаться при 10 000. Специфика блокчейн-стека в том, что узкое место часто не там, где ожидаешь: не база данных, не CPU — а RPC нода, которая не успевает отдава

Направления блокчейн-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1451
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1309
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1005
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1270
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    719
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1011

Масштабирование блокчейн-инфраструктуры: от ноды до WebSocket

Инфраструктура, которая нормально работала при 100 пользователях, начинает сыпаться при 10 000. Специфика блокчейн-стека в том, что узкое место часто не там, где ожидаешь: не база данных, не CPU — а RPC нода, которая не успевает отдавать eth_getLogs, или indexer, который отстаёт на 50 блоков, или WebSocket handler, который дропает соединения под нагрузкой. Масштабирование блокчейн-инфраструктуры — это отдельная дисциплина с непривычными паттернами. Мы занимаемся этим более 5 лет и гарантируем, что ваша инфраструктура выдержит любую нагрузку — пишите, оценим проект бесплатно.

Почему масштабирование блокчейн-инфраструктуры — отдельная дисциплина?

В отличие от классического веба, здесь появляются точки отказа, которые не лечатся простым добавлением серверов: состояние цепочки, лимиты WebSocket, неизменяемые данные на нодах. Каждый слой требует своего подхода — от пула нод до event-driven индексации.

Диагностика: где реальное узкое место

Прежде чем что-то масштабировать — измерьте. Типичные узкие места: latency по каждому RPC методу, queue depth у indexer'а, lag между head блоком ноды и head в вашей БД, throughput WebSocket соединений. Для сбора метрик используем Prometheus и готовые дашборды — входит в объём работ.

// Инструментация RPC вызовов class InstrumentedProvider { private metrics: Map<string, number[]> = new Map(); async call(method: string, params: any[]): Promise<any> { const start = performance.now(); try { const result = await this.provider.send(method, params); this.record(method, performance.now() - start); return result; } catch (err) { this.recordError(method); throw err; } } getPercentiles(method: string) { const samples = (this.metrics.get(method) || []).sort((a, b) => a - b); return { p50: samples[Math.floor(samples.length * 0.5)], p95: samples[Math.floor(samples.length * 0.95)], p99: samples[Math.floor(samples.length * 0.99)], count: samples.length, }; } } 

Как масштабировать RPC слой?

Пул нод с балансировкой

Единственная нода — single point of failure и bottleneck. Минимальная production конфигурация — три ноды с health check и round-robin с пропуском нездоровых. Для stateful операций (подписки, pending transactions) — sticky routing. Код примера ниже — используем в каждом проекте.

class NodePool { private nodes: RpcNode[]; private currentIndex = 0; private healthStatus: Map<string, boolean> = new Map(); async sendRequest(method: string, params: any[]): Promise<any> { for (let i = 0; i < this.nodes.length; i++) { const node = this.nodes[this.currentIndex % this.nodes.length]; this.currentIndex++; if (!this.healthStatus.get(node.url)) continue; try { return await node.send(method, params); } catch (err) { this.healthStatus.set(node.url, false); setTimeout(() => this.healthStatus.set(node.url, true), 30_000); } } throw new Error('All nodes unhealthy'); } } 

Кеширование RPC ответов

Многие запросы идентичны и кешируемы: eth_chainId (24 часа), eth_getCode (1 час — код контракта не меняется), eth_getBlockByNumber для не-latest (1 минута), eth_getTransactionReceipt (5 минут после финализации). Не кешируем latest и pending. Используем Redis — это сокращает количество запросов к ноде на 80%.

const CACHEABLE_METHODS: Record<string, number> = { 'eth_chainId': 86400, 'eth_getCode': 3600, 'eth_getBlockByNumber': 60, 'eth_getTransactionReceipt': 300, }; class CachingRpcProxy { async send(method: string, params: any[]): Promise<any> { const ttl = CACHEABLE_METHODS[method]; if (!ttl) return this.upstream.send(method, params); if (params.includes('latest') || params.includes('pending')) { return this.upstream.send(method, params); } const cacheKey = `rpc:${method}:${JSON.stringify(params)}`; const cached = await this.redis.get(cacheKey); if (cached) return JSON.parse(cached); const result = await this.upstream.send(method, params); await this.redis.setex(cacheKey, ttl, JSON.stringify(result)); return result; } } 

Indexing: от polling к event-driven

Проблема polling

Polling каждые 5 секунд для 10 000 адресов — 2 000 запросов в секунду. Нода захлебнётся. Переходим на событийную модель через EVM logs: один getLogs на диапазон блоков заменяет тысячи отдельных запросов. Экономия — до 90% RPC-нагрузки.

The Graph для сложной индексации

Для агрегаций по пользователям, исторических данных — The Graph subgraph. Self-hosted Graph Node на PostgreSQL 14+ с достаточным I/O. Входит в типовой объём работ: настройка субграфа, деплой, мониторинг.

WebSocket: масштабирование подписок

WebSocket stateful — nginx round-robin не подходит. Используем Redis pub/sud: отдельный сервис публикует события (новый блок, транзакция) в Redis, а WS-серверы подписываются и раздают своим клиентам. Добавление ещё одного WS-сервера — единственное, что нужно для горизонтального масштабирования.

Управление нагрузкой на ноды

Request coalescing — если 100 запросов одновременно просят один ресурс, объединяем их в один RPC вызов. Multicall — один HTTP запрос вместо 100 для balanceOf. Оба паттерна снижают нагрузку на ноду в десятки раз.

Проблема Решение Сложность Экономия RPC-нагрузки
RPC нода — bottleneck Пул нод + балансировка Низкая 50%+
Повторяющиеся одинаковые запросы Request coalescing + Redis cache Низкая 80%+
100+ адресов — мониторинг балансов Multicall + event indexing Средняя 90%+
WS под нагрузкой дропает соединения Redis pub/sub backbone Средняя
Исторические запросы медленные Erigon/Reth archive + query optimization Средняя 70%+
Сложная аналитика on-chain данных The Graph subgraph Высокая

Что входит в нашу работу

  • аудит текущей архитектуры с замером latency, throughput, lag;
  • проектирование решения под ваш стек (Ethereum, Polygon, Arbitrum, Solana);
  • реализация: пул нод, кеширование, event-driven индексация, WebSocket-шлюз;
  • интеграция мониторинга (Grafana, Prometheus, алерты);
  • документация и передача доступов;
  • обучение команды работе с новой инфраструктурой;
  • поддержка в течение месяца после запуска.

Процесс работы

  1. Аналитика — профилируем текущую инфраструктуру, выявляем узкие места.
  2. Проектирование — выбираем паттерны, готовим схему.
  3. Реализация — пишем код, настраиваем сервисы.
  4. Тестирование — нагрузочное тестирование на ваших сценариях.
  5. Деплой и мониторинг — запуск с наблюдением в первые дни.

Сроки ориентировочно

От 2 до 6 недель в зависимости от сложности и количества сетей. Стоимость рассчитывается индивидуально после аудита — пишите, оценим проект за 1-2 дня.

Мы работаем с Ethereum, Polygon, Arbitrum, Optimism, BNB Chain, Solana. Опыт — 10+ проектов, более 5 лет на рынке. Гарантируем качество: все решения проходят ревью и тестирование.