Почему штатные узлы не справляются с потоком данных
Полноузловой клиент держит состояние всей сети и отдаёт данные через RPC-вызовы — это удобно для кошелька, но не для аналитики и продуктовых сценариев. Каждый запрос истории — это либо перебор блоков, либо eth_getLogs по узкому диапазону, и как только в одном блоке оказывается несколько тысяч событий, узел начинает отдавать ответы частями или вовсе срывать соединение по таймауту. Приложение получает не данные, а фрагменты, и восстановить по ним целостную картину уже нельзя.
Отставание индексации — вторая системная проблема. Узел синхронизируется с сетью, но ваш слой чтения живёт отдельным процессом и на пиковой нагрузке не успевает за поступлением новых блоков: очередь растёт, лаг между ончейн-событием и его появлением в вашей базе измеряется десятками минут. Для торговых сценариев, выплат и мониторинга это означает решения, принятые по устаревшим данным.
Третий класс сбоев — пропуск событий при реорганизациях цепочки и разрывах соединений. Если индексатор не отслеживает смену канонической ветки и не умеет откатывать уже записанные записи, в базе остаются события из отброшенных блоков: балансы и истории расходятся с реальным состоянием сети, а найти источник расхождения постфактум почти невозможно.
Штатный узел не рассчитан на то, чтобы быть источником истины для продукта — он спроектирован как участник консенсуса. Именно поэтому под задачи с плотным потоком событий собирают кастомный индексатор блокчейна: собственный конвейер чтения, идемпотентная запись, контроль глубины подтверждений и явная обработка реорганизаций. Разбираем, как это закрывается на практике.
Что даёт собственный конвейер обработки данных
Задержка индексации перестаёт зависеть от чужой инфраструктуры
Публичные обозреватели отдают данные через общий пул: в момент пиковой нагрузки запросы к свежим блокам встают в очередь, и приложение получает состояние сети с отставанием, которое вы не контролируете. Свой конвейер читает блоки напрямую из узла и складывает их в собственную базу — задержка между выходом блока и его доступностью в API держится в предсказуемом коридоре и не растёт вместе с чужой нагрузкой. Для операций, где важна свежесть состояния, это разница между «данные за вчера» и «данные за последние секунды».
Полнота истории и разбор реорганизаций
Внешние источники часто отдают урезанную историю: часть внутренних переводов, логов событий и служебных вызовов в публичный индекс не попадает. Собственный конвейер пишет всё, что прошло через блок, включая внутренние транзакции и события контрактов, — выборки по адресу или токену не теряют записи на глубине. Отдельно закрывается тема реорганизаций: при откате цепи индексатор помечает затронутые блоки недействительными и перестраивает затронутый диапазон, поэтому в базе не остаётся «висящих» состояний, которые потом всплывают в отчётах.
Устойчивость к обновлениям сети и снижение ручных операций
Сеть меняет формат блоков, добавляет новые типы событий, обновляет контракты — публичный обозреватель под это подстраивается сам, а ваши выборки ломаются молча. Свой конвейер описывает схему данных явно: при изменении формата правится один модуль разбора, остальная логика и API остаются прежними. Это убирает регулярные ручные доработки при обновлениях сети — команда не тратит циклы на разбор «почему поле пропало», а получает стабильный поток данных, на который можно опираться в продукте.
Способы организации индексации: сравнение режимов
Выбор режима определяет не только скорость появления данных в индексе, но и стоимость инфраструктуры, и то, как система переживает пересборку истории. На практике чистых схем две, а рабочая конфигурация почти всегда третья — гибридная. Ниже — сравнение по тому, когда каждый режим уместен и где начинает упираться.
| Режим | Когда подходит | Ограничения |
|---|---|---|
| Потоковая индексация | Нужны свежие данные с задержкой в секунды: балансы, операции, события контрактов в реальном времени | Требует устойчивого соединения с узлом и очереди; при разрыве возможны пропуски, нужен контроль порядка и повторная доставка блоков |
| Пакетная обработка | Первичная загрузка истории, аналитика, отчёты, где важна полнота, а не секунды | Данные появляются с задержкой; на больших диапазонах блоков растёт время прохода и нагрузка на узел |
| Гибридный режим | Продукт с живым интерфейсом и глубокой историей одновременно | Сложнее в поддержке: два контура, согласование состояния и единая точка сверки |
Почему гибрид закрывает больше задач
Потоковый контур держит «голову» цепи и отдаёт свежие события, пакетный догоняет историю и пересчитывает участки при изменении логики разбора. Разделение снимает главное противоречие: живой интерфейс не ждёт, пока переиндексируется вся история, а пересборка не тормозит приём новых блоков.
Ключевой элемент здесь — идемпотентность записи и чекпойнты по высоте блока. Если обработка упала на середине диапазона, контур поднимается с последней зафиксированной точки, а не начинает заново. Это превращает сбой из «переиндексируем всё» в «догоняем пропущенное».
Ограничения гибрида — организационные, а не технические: нужна дисциплина в схеме данных и единая точка сверки, иначе контуры начинают расходиться. Мы закладываем её на этапе проектирования, поэтому режим выбирается под задачу, а не под удобство реализации.
Как мы выстраиваем кастомный индексатор блокчейна
Работу начинаем с аудита инфраструктуры: смотрим, какие узлы уже подняты, как настроена синхронизация с сетью, какие запросы к блокчейну идут сегодня и какие из них тормозят продукт. На этом этапе фиксируем целевые метрики — глубину индексации, допустимое отставание от последнего блока, набор полей в ответе — чтобы дальше проверять результат по цифрам, а не по ощущениям.
- Аудит инфраструктуры. Разбираем текущие узлы, хранилище, нагрузку и точки отказа. Определяем, что переиспользуем, а что придётся заменить, и где индексатор упрётся в потолок при росте числа запросов.
- Проектирование конвейера. Проектируем поток данных: приём блоков, разбор событий, обогащение, запись в хранилище, отдача по API. Заранее закладываем повторную обработку при сбое — чтобы пропущенный блок не оставлял дыру в данных.
- Настройка индексатора. Поднимаем сервисы, настраиваем правила отбора событий и схемы хранения под конкретные запросы продукта. Отдельно настраиваем мониторинг отставания и оповещения при остановке синхронизации.
- Проверка полноты. Сверяем проиндексированные данные с данными сети на контрольных отрезках: сколько событий пропущено, совпадают ли балансы и состояния. Прогоняем нагрузочные сценарии и проверяем поведение при перезапуске.
- Передача и сопровождение. Отдаём конфигурации, схемы и документацию, обучаем команду заказчика. Дальше сопровождаем: следим за обновлениями сети и корректируем правила индексации.
Каждый этап заканчивается проверяемым результатом, поэтому отклонение видно сразу, а не на проде. Опишите задачу — вернёмся с оценкой и планом работ.
Артефакты и документация после внедрения
После запуска индексатора команда не остаётся с «чёрным ящиком»: всё, что описывает поведение системы, передаётся в виде рабочих материалов. По ним ваш инженер сможет поднять стенд с нуля, повторить конфигурацию и понять, почему обработка устроена именно так.
- Конфигурации индексатора и узлов: параметры подключения к сети, глубина переобработки при реорганизациях, лимиты на размер батча, настройки повторных попыток.
- Схемы потоков данных: от приёма блоков до записи в хранилище и отдачи по API — с точками, где возможны задержки и потери.
- Регламенты обслуживания: плановые перезапуски, переиндексация при смене схемы, порядок действий при расхождении состояния с сетью.
- Политики доступа: роли для чтения и записи, разграничение по эндпоинтам, правила ротации ключей и секретов.
- Описание схемы хранения: таблицы, индексы, стратегия партиционирования и очистки устаревших данных.
- Набор проверок: health-эндпоинты, метрики отставания от головы сети, алерты на остановку обработки.
- Инструкция по развёртыванию: порядок поднятия компонентов, зависимости, переменные окружения, требования к ресурсам.
- Журнал решений: какие альтернативы рассматривались и почему выбран текущий вариант — чтобы будущие изменения не ломали логику.
Материалы передаются в репозитории и вики вашей команды, а не в переписке. Мы остаёмся на связи на этапе, когда ваши инженеры вносят первые правки, — это снижает риск, что документация разойдётся с реальной конфигурацией.
Кейс: как мы сократили задержку индексации втрое
Заказчик — сервис аналитики по сети на базе EVM-совместимого блокчейна — пришёл с симптомом, а не с задачей: данные в дашбордах отставали от сети, а по утрам индексатор отваливался на переобработке. Свой индексатор они писали под задачу, но он читал блоки строго последовательно, одной нитью, и хранил состояние в одной таблице без партиционирования. На пике нагрузки очередь неразобранных блоков росла быстрее, чем её успевал разгребать воркер.
Что было до
Задержка между появлением блока в сети и его доступностью в API доходила до 40 минут на пиках. Реорги глубже двух блоков ломали состояние: индексатор не откатывал уже записанные события, и в базе оставались «висячие» записи из отменённой ветки. Раз в несколько дней процесс падал по памяти — перезапуск означал полный пересчёт с нуля и ещё несколько часов простоя.
Что изменили
Разнесли чтение и запись: отдельный сборщик тянет блоки пачками и кладёт их в очередь, пул воркеров разбирает её параллельно по диапазонам. Ввели явную обработку реоргов — при расхождении хешей индексатор откатывает затронутые диапазоны по журналу и перечитывает каноническую ветку. Состояние разложили по партициям с чекпоинтами: после падения процесс продолжает с последней подтверждённой высоты, а не с нуля.
Что стало
| Метрика | До | После |
|---|---|---|
| Задержка индексации на пике | до 40 мин | 12–13 мин |
| Отказы из-за реоргов | регулярно | класс устранён |
| Простой после сбоя | часы, полный пересчёт | секунды, с чекпоинта |
Задержка сократилась втрое, ручные перезапуски ушли из процесса совсем. Отдельно вынесли метрики самого индексатора — глубину очереди, лаг по высоте, число откатов — чтобы команда заказчика видела деградацию до того, как её заметят пользователи.
Чем отличается кастомный индексатор от готовых решений?
Готовые индексаторы — это универсальные конвейеры: они читают блоки, декодируют стандартные события и раскладывают их в собственную схему хранения. Пока вы работаете с типовыми контрактами и одной сетью, этого достаточно. Проблема начинается там, где логика вашего продукта расходится с тем, что готовый инструмент умеет отдавать «из коробки»: нестандартные контракты, собственные структуры данных, пересчёт состояния по историческим блокам, объединение нескольких сетей в один запрос.
Кастомная разработка начинается с вопроса «какие запросы должны выполняться быстро», а не «какие данные есть в блоках». Инженеры проектируют схему хранения под конкретные сценарии: агрегаты по адресам, историю балансов на произвольную высоту, связки между событиями разных контрактов. Готовое решение такую схему не предложит — его модель фиксирована, и вы подстраиваете продукт под неё, а не наоборот.
Критерии выбора простые. Если нужен обзор сети, стандартные переводы и события популярных контрактов — готовый инструмент закроет задачу быстрее и дешевле в поддержке. Если требуются собственные метрики, нестандартная агрегация, глубокая история или несколько сетей в одном ответе — универсальный конвейер упрётся в ограничения, и обходные пути съедят больше ресурсов, чем собственная разработка.
Отдельно стоит устойчивость к реорганизациям цепи и сбоям узлов. В кастомном индексаторе логика откатов и повторной обработки блоков проектируется под ваши данные: понятно, какие записи пересчитываются, а какие остаются валидными. У готовых решений это чёрный ящик — при расхождении приходится разбираться, что именно потерялось.
Сравнение стоит вести не по числу поддерживаемых сетей, а по тому, насколько быстро вы получите ответ на новый вопрос к данным. Готовый инструмент отвечает на уже заложенные вопросы, кастомный — на те, которые появятся у продукта завтра.
Частые технические сомнения при внедрении
Индексатор — это не разовая интеграция, а сервис, который живёт вместе с сетью: меняются контракты, добавляются события, выходят обновления узла. Поэтому первое, что проверяет технический заказчик, — не «заработает ли», а «что будет через полгода». Ниже — сомнения, которые всплывают на каждом проекте, и как мы их закрываем инженерно.
Насколько сложно поддерживать кастомный индексатор своими силами?
Сложность не в коде, а в эксплуатации: реорги, отставшие блоки, рост базы, переиндексация после апгрейда контракта. Мы отдаём сервис с метриками (лаг индексации, глубина очереди, доля ошибок), алертами на отставание и регламентом переиндексации — команда видит состояние без чтения исходников. Обновление схемы событий делается миграцией, а не переписыванием с нуля.
Совместимо ли это с нашей текущей инфраструктурой и узлами?
Индексатор подключается к вашим нодам или к внешним провайдерам через стандартные интерфейсы, а результат отдаёт в привычное хранилище — реляционную базу, поисковый движок или очередь. На входе — обычные RPC-вызовы и подписки на события, на выходе — схема, которую потребляет ваш бэкенд. Миграция не требует останавливать текущие сервисы: новый индекс наполняется параллельно, переключение — сменой источника чтения.
Как обеспечивается безопасность и целостность данных?
Данные берутся из подтверждённых блоков с учётом финальности, поэтому в индекс не попадают события из отменённых веток. Доступы разграничены: сервис индексации имеет только чтение к узлу и запись в свою схему, ключи подписи хранятся отдельно от процесса обработки. Каждое событие сопровождается ссылкой на блок и транзакцию — любую запись можно проверить на цепочке.
Что если сеть или контракт изменятся после запуска?
Апгрейд контракта — штатный сценарий: новая версия событий описывается отдельной схемой, старые данные остаются доступными. При смене формата мы добавляем обработчик и запускаем переиндексацию нужного диапазона блоков, не трогая остальную историю. Версионирование схемы заложено с самого начала, поэтому переход проходит без простоя.
Опишите вашу сеть и объём событий — вернёмся с оценкой и планом внедрения.
Обсудим вашу задачу и предложим план работ
Чтобы предложить план работ, а не общие слова, нам нужно понять вашу задачу на уровне данных: какие сети и контракты индексируем, какие события и вызовы методов важны, что именно должно попадать в ответы API. Опишите сценарий — откуда приходят запросы, какие выборки критичны по скорости, нужна ли историческая глубина или только свежие блоки. По этому описанию мы соберём черновик архитектуры и вернёмся с оценкой сроков и этапов.
На первом разговоре уточняем требования и границы:
- источники данных: какие сети, ноды или провайдеры, нужен ли доступ к архивным узлам;
- модель данных: какие сущности, связи и агрегаты должны быть в индексе, как часто пересчитываются;
- нагрузка и задержка: сколько запросов в секунду ожидается, какая задержка от блока до ответа допустима;
- устойчивость: что делаем при реорганизации цепи, пропуске блока, падении узла — нужен ли автоматический догон;
- доступы и инфраструктура: где разворачиваем, свои серверы или облако, кто владеет ключами и данными;
- интеграции: какие сервисы и команды будут читать индекс, в каком формате им удобно получать данные;
- развитие: какие метрики и выборки появятся позже, чтобы заложить их в схему без переделки.
Дальше предлагаем следующие шаги: фиксируем согласованные требования в коротком документе, показываем схему потока данных и состав индекса, разбиваем работу на этапы с проверяемым результатом на каждом. Вы видите, что и в каком порядке делается, где можно запустить первую версию и как она расширяется.
Опишите задачу в свободной форме — вернёмся с оценкой и планом работ.







