Год с 1С:Шиной в проде: что ломается на длинном аптайме

17.08.26

Интеграция - Перенос данных 1C

Если у вас интеграционная шина и обмены иногда встают непонятно почему, эта статья про то, где искать. Главный вывод за год эксплуатации: очереди самой шины виноваты редко. Отставание копится на стороне 1С, и обычный мониторинг длины очереди его не ловит совсем: очередь короткая, всё зелёное, а канал стоит сутки. Внутри пять поломок, которые не воспроизводятся на тестовом стенде и вылезают только на длинном непрерывном аптайме, и три случая, когда шина отчиталась «доставлено», а данные в базу не приехали. По каждой: симптом, куда мы полезли сначала и почему мимо, настоящая причина и что помогло. Отдельно история про то, как врал наш мониторинг, и как проверить свой за полчаса. В конце чеклист на двадцать пунктов: что задать в контейнере до первого запуска, что мониторить кроме длины очереди и чем рестарт шины отзовётся в базах-приёмниках.

Один узел. Четыре ядра, 15 гигабайт памяти, Docker на Linux. Через него идёт около миллиона сообщений в сутки между десятком систем, и при этом управляющий слой (консоль и её API) умирал раз в один-два дня.

Ни одно падение не упиралось в производительность процессора.

Это разбор эксплуатации 1С:Шины 6.1.6 в проде розничной сети. В центре связки учётная система на 1С:УПП, вокруг неё зарплатная база, бухгалтерия, фронт-офис касс, кассовый сервис, BPM, WMS, CRM с программой лояльности, сервисы доставки и инвентаризации.

Две оговорки. Наблюдения за год, а замеры за последние тридцать суток: хранение метрик настроено на месяц, годовых рядов нет, экстраполировать не буду. И про жанр: как Шину разворачивать и как её наблюдать, на Инфостарте уже написано, в том числе свежий разбор отказоустойчивости от июля этого года. Повторять не буду, в паре мест сошлюсь.

Отдельная глава дальше - про то, как наш собственный мониторинг показывал 3,8 миллиона ошибок, которых не было.

 

Словарь на три строки

Процесс это одна интеграционная схема, у нас их 18. Узел это точка внутри схемы, где сообщение обрабатывается или передаётся дальше, их 173. Приложение это единица развёртывания внутри Шины, их запущено 15, и рестартовать их можно по отдельности, не трогая контейнер. Канал это направление обмена на стороне 1С, их 62. Участник это учётная запись подключения к Шине: кто под ней подключился, тот и забирает сообщения.

Про брокеры - дальше их будет два. Внутри Шины едет встроенный ActiveMQ Artemis. Рядом стоит внешний RabbitMQ, через него часть систем общается с Шиной. Ломались они по-разному.

 

Пять дефектов, которые копились с аптаймом

Теперь то, ради чего вы открыли статью. За год набралось пять дефектов, и все пять объединяет одно: на коротком стенде они невидимы, потому что стенд живёт сутки и пересоздаётся. Это не значит, что они невоспроизводимы - как минимум два повторяются за час.

1. Дефолт Docker в десять секунд превращал баг брокера в отказ

Журнал встроенного брокера рос на 10 гигабайт в сутки линейно с аптаймом. Пишется он файлами-сегментами, и их накопилось 3 956 - это 38 гигабайт. Диск расширяли с 98 до 148 гигабайт и упирались снова.

В логе при этом Cannot find add info ... on compactor - известный баг компактации Artemis, то есть уплотнения журнала, когда брокер выбрасывает отработанные записи. Баг воспроизводится во всех версиях вплоть до 2.24.0, а внутри Шины едет более старая 2.14.0 от 2020 года, то есть наша под него попадает. Внешнего broker.xml нет, настройками брокера не лечится. Пятилетний брокер без доступа к конфигу внутри коммерческого продукта - мягко говоря, не то, что ожидаешь от готового решения.

Триггер оказался не в брокере. В docker-compose.yml не был задан stop_grace_period, дефолт Docker - десять секунд. Брокер с большим журналом за это время закрыться не успевает, получает SIGKILL, журнал повреждается, компактор ломается, дальше рост.

Фикс целиком:

stop_grace_period: 300s

Результат: аптайм 8,5 суток, журнал 93 сегмента вместо 3 956, это 930 мегабайт против 38 гигабайт. Вхождений Cannot find add info в логах ноль.

Но заслугу этой строке я приписать не могу. Одновременно с ней мы выключили режим разработки (следующий дефект), а он ронял управляющий слой раз в двое суток. Меньше падений - меньше рестартов - меньше SIGKILL - меньше повреждений журнала. Это объясняет результат ничуть не хуже, чем grace period, а разделить вклад двух изменений я не могу: они ушли в одно окно, контрольной группы нет. Чтобы доказать вину дефолта, надо было замерить, сколько занимает штатное закрытие брокера. Не замерил.

Как журнал дорастал до 38 гигабайт при падениях раз в двое суток: 38 на 10 - почти четверо суток роста. Значит он переживал аварийные рестарты и копился сквозь них, что логично при повреждённом журнале: схлопнуться он уже не мог.

Отдельное наблюдение: при штатном рестарте восстановление журнала (recovery) схлопнуло его с 38 гигабайт до 270 мегабайт. То есть 37,7 гигабайта были мёртвыми записями - при условии, что recovery ничего не выбросил. Сохранность сверкой по идентификаторам мы не проверяли, хотя ниже, в инциденте с посторонним потребителем, я сам показываю, что статусам верить нельзя.

Этот дефект - из тех двух, что повторяются за час: налить журнал на стенде и дёрнуть docker stop, вся проверка.

2. Управляющий слой умирал раз в двое суток

Консоль и Console API переставали отвечать: запросы доходили, ответа не было. Брокер при этом живой, служебная проверка живости (heartbeat) отдаёт 200, процессор простаивает, обмены стоят.

В служебном логе незакрытых ресурсов сто процентов записей приходило из одной точки кода платформы: незакрытый результат запроса к внутренней базе консоли на H2 - это встроенная Java-СУБД, живёт файлом рядом с приложением. Темп примерно шесть штук в минуту, около 8 600 в сутки.

Усилитель нашёлся рядом: все приложения работали в режиме разработки с включённой отладкой. Тогда их было семнадцать, сейчас запущено пятнадцать. Фоновое задание опрашивало статус среды разработки и дёргало тот самый метод с утечкой. Как режим разработки оказался включён на всех продуктивных приложениях и дожил до привычных падений раз в двое суток - вопрос без хорошего ответа. Никто не смотрел.

Выключили - утечка остановилась ровно в момент изменения, не постепенно. Счётчик незакрытых результатов за весь новый аптайм 67, прирост за сутки ноль.

Чего в этой истории не хватает. Я показываю темп утечки, но не показываю предел, в который она упиралась. Восемь с половиной тысяч незакрытых результатов в сутки при пуле в несколько десятков соединений исчерпали бы его за минуты, а отказ наступал раз в двое суток - значит упиралось что-то другое: дескрипторы, память, что-то третье. Я не снял ни дамп потоков в момент зависания, ни лимиты. Связь «выключили режим разработки - перестало падать» у меня есть, механизма нет.

Урок про мониторинг тут важнее урока про флаг: сервер отвечал «я жив» ровно тогда, когда управление и обмены были мертвы. Наш watchdog проверял корневой URL и получал 301.

3. Диск был свободен наполовину, а inode заканчивались

Диск занят на 84 процента, 125 гигабайт из 148. Терпимо. А вот inode на 85 процентах, 8,27 миллиона, и это дни до аварии.

При включённом хранении доставленных Шина пишет каждое сообщение в два места: описание в базу PostgreSQL, тело - отдельным файлом на диске (тело бывает любым, от короткого XML до вложений на мегабайты, потому и файлом). База ротируется корректно, retention, то есть срок хранения, сутки. А файлы с телами сборщик мусора платформы не забирает никогда.

Лечение: ночной cron, удаляющий эти файлы старше retention. Результат замерен: диск 125 → 90 гигабайт, inode 8,27 → 1,53 миллиона, то есть освободилось 35 гигабайт и 6,74 миллиона файлов. Моя прикидка до уборки - «около 7,5 миллиона файлов на 40-45 гигабайт» - оказалась завышенной, верьте замеренной дельте.

Предупреждаю: рекомендация разрушительная. Мой вывод «эти файлы осиротели» держится на логике. Выборку имён с базой я не сверял. И «не удаляются никогда» - наблюдение за месяц на установке, где половину времени приложения крутились в режиме разработки и падал управляющий слой; может, сборщик мусора просто не отрабатывал по этой причине. Прежде чем ставить у себя cron, который сносит файлы из хранилища платформы, проверьте выборку на наличие ссылок.

Почему накопилось ровно месячный объём, если удаление не работает вовсе: хранение доставленных мы включали точечно в июне, под расследование инцидента с пропажей сообщений. Включили, разобрались, забыли выключить. Через месяц оно чуть не положило хранилище.

4. Скрипт бэкапа, который тихо умер

tar на живых данных отдаёт file changed as we read it и возвращает код 1. А в скрипте стояло set -euo pipefail - режим «умри при первой же ошибке», - и он честно убивал его на середине.

Итог: скрипт в crontab был, свежих бэкапов не было. Старые лежали, больше пятидесяти снапшотов на 24,5 гигабайта, то есть когда-то он работал и сломался в какой-то момент, а когда именно, мы не знаем: ротации не было, дат никто не смотрел. Плюс 7,1 гигабайта незавершённого архива внутри контейнера.

Проверяется это наличием свежего файла нужного размера. Строка в расписании не доказывает ничего.

5. Отвал потребителя от внешнего брокера

Это второй брокер из словаря, внешний, и ломается он, как и обещано, иначе.

Очередь есть, сообщения есть, потребителей ноль. Шина отвалилась как потребитель. Лечится рестартом приложения, контейнер трогать не нужно.

В агрегате это выглядело как 26 потребителей на 28 очередей. Само по себе это ничего не доказывает: часть очередей у нас без потребителей by design, о чём отдельный сюжет ниже. Правильный признак - очередь, где одновременно есть необработанный остаток и ноль потребителей.

 

Отставание копится не в Шине, а в 1С

Все пять дефектов ломали саму Шину. Самый дорогой отказ года выглядел иначе: со стороны шины всё было идеально.

На стороне приёмника 1С складывает сообщения до разбора в буфер - физически это три регистра сведений: основной в учётной системе, фронт-офис касс и кассовый сервис.

Максимумы за 30 дней по каждому:

Буфер Максимальный возраст Максимальная глубина
основной 111 698 с = 31,0 ч 2 863
фронт-офис касс 2 532 с = 0,7 ч 963
кассовый сервис 2 232 с = 0,6 ч 391

Тридцать один час. Очереди самой Шины в этот момент были пусты.

Почему это не то, что вы подумали

Первая реакция на «31 час отставания» - разбор встал, в буфере гора сообщений. Посчитаем: основной буфер, дальше я буду звать его регистром-приёмником, принимает 6,18 миллиона записей за 14 дней, это 441 тысяча в сутки. Если бы разбор стоял 31 час, там лежало бы порядка 570 тысяч записей.

Их там не было. Замер по часам во время инцидента:

18.07 07:31   возраст  1,1 ч   в буфере   44
18.07 23:31   возраст 10,7 ч   в буфере  197
19.07 11:31   возраст 22,7 ч   в буфере  310
19.07 19:31   возраст 30,7 ч   в буфере  196   ← пик возраста

44 сообщения, 310, 196.

Разбор всё это время исправно работал, а стояла голова: одно сообщение не разбиралось и старело вместе с часами.

Причём таких сообщений было минимум два. Между первым и вторым замером прошло 16 часов, а возраст вырос только на 9,6 часа - значит первая голова как-то ушла, её сменила следующая. Дальше, с 23:31, возраст растёт синхронно с часами: за 12 часов плюс 12, за 8 часов плюс 8 (10,7 → 22,7 → 30,7). Вот эта часть чистая.

Чего я не знаю и знать бы хотел: что именно застряло. Тип сообщения, что его держало, чем эпизод кончился - сам рассосался, руками или рестартом. В разборе этого нет, и поэтому «мониторьте возраст» у меня получается советом мерить симптом болезни, которую я не диагностировал.

Эпизод повторился через два дня по той же схеме и доехал до 16,4 часа. Два случая это «повторилось». Воспроизводимость означала бы, что я умею вызвать отказ по требованию, а я не умею.

Максимум глубины, кстати, случился в другой день, 29 июля, и возраст старейшего был тогда ноль часов. Два максимума, выглядящие одним инцидентом, не связаны вообще.

Почему это касается и вас

Любой мониторинг длины очереди в те двое суток показывал зелёное.

А канал стоял тридцать один час.

Этот класс отказов ловится возрастом самого старого необработанного сообщения. Длина ловит остановку разбора, возраст ловит застрявшую голову. Это разные отказы, и второй при нормальной глубине невидим.

 

Когда соврал наш собственный мониторинг

Этот сюжет мы нашли, когда готовили материал, и он мне нравится больше всех остальных.

Метрика «ошибок текстового лога брокера» показывала 3 801 769. В логах при этом ноль таких строк.

Экспортёр - скрипт, который отдаёт метрики в Prometheus, - выполняет два действия подряд: берёт inode файла и считает совпадения по шаблону. Первую строку вывода читает как inode, вторую как счётчик. Лог у нас ротируется каждые девять минут, при журнале, растущем на десятки гигабайт, иначе никак. И в момент ротации grep не находит файл и не отдаёт вторую строку. Код невозмутимо принимает номер inode за число совпадений.

3 801 769 - это буквально inode файла лога. Метрика питала боевой алерт и месяцами никого не разбудила, что само по себе говорит о качестве наших алертов больше, чем хотелось бы.

Рядом нашлась вторая: максимум времени ответа консоли ровно 30,000 секунды. Ровно. Это не задержка, а штрафная заглушка при неудачном запросе токена авторизации к консоли. Как индикатор отказа годится, как метрика задержки нет - реальный 95-й перцентиль 23 миллисекунды.

И третий случай того же сорта, только жертвой был я сам. Считая объём трафика, я снял его вторым источником - со служебных HTTP-адресов приложений, отдающих счётчики. Получилось 8,47 миллиона сообщений за 8,5 суток аптайма, то есть 996 тысяч в сутки против 995 у Prometheus, расхождение 0,16 процента. Красиво.

Только Prometheus эти же адреса и опрашивает, счётчик там тот же самый. Я дважды прочитал одно число и чуть не назвал это независимой проверкой. Проверено на деле другое: сбор и хранение метрик ничего не теряют по дороге. Метод подсчёта этим не подтверждается.

А теперь неудобный вопрос к самому себе. Если один экспортёр показывал inode вместо счётчика, второй писал заглушку вместо задержки, а третью проверку я сам себе выдумал, почему вы должны верить 31 часу из того же хозяйства? Отвечаю: возраст сообщения считается из поля времени, которое отдаёт сама 1С. На часы машины мониторинга мы не смотрим с тех пор, как наступили на их расхождение с сервером. Когда именно перешли, до июльского эпизода или после, у меня не записано. Значит и к 31 часу оговорка нужна: порядок величины я подтверждаю почасовым рядом, точность до минут не гарантирую.

Урок шире Шины: мониторинг надо верифицировать. Возьмите пару самых пугающих метрик и сходите руками в источник. У нас на это ушло полчаса.

И грабля оттуда же: правка правил алертинга через sed -i не применяется. Файл, проброшенный в контейнер поштучно (bind-mount), привязан к inode, а sed -i создаёт новый файл. На хосте правка видна, контейнер читает старый, перезагрузка конфигурации отвечает 200 и грузит старое. Лечится записью поверх или рестартом. Это вторая из обещанных быстро воспроизводимых граблей. В пятёрку дефектов она не попала, потому что к длинному аптайму отношения не имеет вовсе: повторяется на ноутбуке за пять минут.

 

Три инцидента с данными и одно условие

Дефекты выше ломали саму Шину. Следующие три истории хуже: в них страдали данные, а журнал Шины при этом показывал «доставлено».

Посторонний потребитель съедал часть потока

Сообщение помечено «доставлено» в журнале Шины, а в продуктивной базе его нет.

Причина: второй сеанс 1С конкурентно читал того же участника шины, что и продуктив. Сообщения делились между ними.

Масштаб - тут надо аккуратно. Из пятидесяти проверенных сообщений в проде нашлись восемнадцать: потеряно 64 процента выборки. На всё окно, а это около семи тысяч сообщений, доверительный интервал даёт от 51 до 77 процентов, то есть от 3,5 до 5,4 тысячи. Точное «около 4 500», которое я написал сначала, этой точности не заслуживает.

Хуже другое: сплошная проверка была доступна. Идентификаторы всего окна есть, регистр с 6,18 миллиона записей есть, запрос пишется за минуту. Мы этого не сделали, и правильного ответа у меня нет - есть интервал.

Retention регистра-приёмника 14 дней против шести часов на Шине, поэтому «нет в регистре» не объясняется вычисткой по сроку. Но полностью исключить отбраковку бизнес-логикой или собственной дедупликацией приёмника я не могу: этой проверки мы тоже не делали.

Что спасло: приёмник идемпотентен, дубли отбрасываются, поэтому мы просто переслали всё окно целиком. Как именно устроена дедупликация - по идентификатору сообщения, по хешу, с каким окном - в разборе не зафиксировано. Вопрос при этом самый практический во всей статье. Знаю только объём: 91 781 повторный идентификатор в сутки, и это 21 процент от суточного потока этого приёмника (441 тысяча записей). От общего потока Шины доля была бы вчетверо меньше, поэтому знаменатель называю явно.

Двадцать процентов штатных повторов - повод разбираться, в статистику такое записывать рано. Мы не разбирались.

Главный урок: «доставлено» в журнале шины не равно «загружено» в системе-приёмнике. Счётчик недоставленных этот случай не ловит по построению - для Шины всё штатно. У нас 61 недоставленное на 26 миллионов, 2,5 на миллион, цифра прекрасная и совершенно не про то.

Переотправка - только кнопкой в консоли, публичного метода нет, автоматизировать можно роботом по UI. Для промышленной интеграционной платформы это странно.

Рестарт Шины клинит очереди в чужой базе

Cannot insert duplicate key по уникальному индексу входящей очереди канала. Очередь встаёт, сообщения не грузятся.

Позицию в очереди задаёт Шина. После рестарта она начинает нумеровать позиции с более раннего значения, и новые сообщения получают номера, которые 1С уже видела и считает обработанными. Очереди строго FIFO, поэтому одна коллизия в голове блокирует канал целиком.

Масштаб: крупнейшая таблица очереди 2,78 миллиона строк. Автолечение мы написали отдельным сервисом: он обходит очереди раз в минуту, за 30 дней 48 833 прохода, ноль ошибок, срабатывало около 22 раз.

Критерий, по которому сервис удаляет строку: позиция, где одновременно висит и необработанное, и уже обработанное сообщение с тем же идентификатором. Ошибиться тут можно, и цена ошибки - потерянное сообщение, поэтому у нас он работает только на входящих очередях и только на точном совпадении идентификатора.

Урок: рестарт Шины бьёт и за её пределами, по базам-приёмникам.

Сообщения в очереди без потребителя

Девять подтверждений улетели с ключом маршрутизации базовой очереди, то есть с адресом, по которому брокер выбирает очередь. У базовой потребителей ноль, а уйти они должны были в специализированную. До этого очередь была пуста весь месяц, залёт случился одной пачкой, предположительно в окно переподключения.

Очереди без потребителей by design - тихая дыра. Их надо либо явно исключать из алертов, либо мониторить отдельно.

Условие, при котором инциденты нерасследуемы

Это не инцидент, а рамка для всех трёх. Тела сообщений на шине живут около шести часов - столько доступна переотправка. Описания в базе живут сутки, но без тел бесполезны. Регистр в 1С хранит 14 дней.

Через сутки после сбоя расследовать уже не по чему. Это обратная сторона третьего дефекта: хранение доставленных либо съедает диск, либо его нет, когда нужно расследовать.

 

Теперь цифры, и сначала о том, как они посчитаны

До сих пор были истории. Дальше таблицы - но прежде надо сказать, как они посчитаны, иначе им нельзя верить.

Метрика node_message_counter считает сообщения на каждом узле схемы. Просуммировать все узлы - каждое сообщение посчитается по числу пройденных узлов. У нас это шестикратная разница: 26,1 миллиона против 147,5 миллиона за одно окно.

Поэтому считаем так:

  • сообщения = сумма по процессам от максимального счётчика среди узлов процесса;
  • события на узлах = сумма по всем узлам, и это метрика работы; сообщений она не считает.
sum(max by (process) (increase(node_message_counter[30d])))

Увидите в чужой статье про интеграцию красивое число - спросите, каким из двух способов оно получено.

Метод занижает, и это надо сказать прямо. Внутри одного процесса могут идти несколько независимых встречных потоков: в самом нагруженном у нас поток в одну сторону даёт 10,0 миллиона, встречный 9,8 миллиона. Максимум берёт только первое.

Насколько? Недоучёт 9,8 миллиона сверх посчитанных 26,1 - около 38 процентов по одному процессу. Сколько таких среди остальных семнадцати, не считал. Поэтому дальше везде читайте «не менее». Слово «вдвое» я писать не стану: из моих чисел оно не выводится.

Настоящая независимая сверка - число загруженных записей у приёмника с коэффициентом «сообщение к записям». Её я не делал.

 

Что показали замеры

Четыре среза: поток, суточный профиль, ресурсы, очереди.

Поток

Все цифры сняты 17 августа.

Показатель Значение
Сообщений за 30 дней не менее 26 092 008
Среднее по суткам (сумма за окно, делённая на 30) около 870 000
Медиана по суткам 830 547
Самые тяжёлые сутки 2 976 871
В среднем около 10 сообщений в секунду
Пик пятиминутного окна 129,4 в секунду
Пик часового окна 102,6 в секунду

Медиана и пиковые сутки разошлись в 3,6 раза.

Сразу оговорюсь, потому что вопрос законный: размер и состав типичного сообщения я не мерил. Поэтому «миллион в сутки» примерить на свою систему по этим цифрам нельзя, не зная, что лежит у нас внутри сообщения. Сравнивать имеет смысл динамику и профиль; абсолютные величины тут мало что дают.

Здесь я чуть не обманул сам себя. Первые десять суток окна давали в среднем 722 788 сообщений, последние десять - 958 108. Рост на 32,6 процента, и я сходу написал абзац про растущую нагрузку, по которой бессмысленно планировать. Абзац пришлось выкинуть: в первые десять суток управляющий слой падал раз в один-два дня и обмены стояли, в последние 8,5 суток - ни разу. Я измерил не рост нагрузки, а собственное восстановление после фиксов. Тридцать два процента это мера потерь на простоях, и так цифра куда интереснее.

Если считаете тренд по окну с инцидентами, вы считаете не тренд. Сначала аптайм, потом график.

Суточный профиль

Разброс между самым тихим ночным часом и пиковым дневным - больше тридцати пяти раз: 2,9 сообщения в секунду против 102,1.

Оговорка: числа с разных суток. Пиковый час это максимум за тридцать дней, ночной провал с типичных суток. Внутри одних суток размах меньше, отдельного замера нет. Максимум часа против типичной ночи - тот самый приём, о котором я предупреждал выше, называю его прямо.

Ещё у ночи есть своя вершина: 47,5 сообщения в секунду в час пакетного обмена, там, где ждёшь провала. Если строить порог от «ночью тихо», он сработает по этому батчу.

Алерт с фиксированным порогом на поток будет фолзить. У нас он звонил каждую ночь, пока мы не добавили условие на наличие необработанного остатка.

Запас по ресурсам

Память в таблице ниже - по контейнеру Шины, хост считается отдельно: там ещё внешний RabbitMQ и вспомогательные сервисы.

Ресурс Сейчас Максимум за 30 дней
CPU хоста 24,7 % 59,7 %
CPU в среднем 21,7 % -
Память контейнера Шины 5,5 ГБ 8,25 ГБ
load average (1 мин) 0,73 6,91

load average - среднее число процессов, ждущих выполнения. По процессору запас кратный (миллион сообщений при 22 процентах), по памяти скромнее: максимум контейнера 8,25 гигабайта при 15 на всём хосте, запас меньше двукратного, и лимит самого контейнера я не догадался зафиксировать.

Пиковый load average 6,91 на четырёх ядрах выглядит тревожно, и у меня была версия, что это очередь на диск - журнал встроенного брокера тогда рос на 10 гигабайт в сутки, а файлы прибывали сотнями тысяч в день (оба сюжета разобраны выше, в дефектах 1 и 3).

Замер её не подтвердил. iowait, то есть доля времени процессора в ожидании диска, в среднем 1,01 процента, максимум 11,12. Утилизация диска в среднем 5,56 процента, максимум 51,53. Процессов, застрявших в ожидании диска, максимум пять.

Но и объяснить пик мне нечем. В отдельные мгновения готовых к выполнению процессов было до сорока. Но сорок готовых на четырёх ядрах дали бы стопроцентную загрузку, а максимум по хосту 59,7. Значит это доли секунды, и пиковый load ими не объясняется.

Вдобавок iowait и утилизацию диска я снял за неделю, а максимум load average взят за тридцать суток. Отсутствие iowait в одном окне ничего не говорит про максимум в другом. Итог: причину пикового load average я не установил.

Очереди самой Шины не копятся

Показатель Значение
В очередях сейчас 56 сообщений
Максимум за 30 дней 422
95-й перцентиль 49
Максимум неподтверждённых 22

Двадцать шесть миллионов сообщений в месяц - и максимум очереди 422.

Оговорка, которую обязан применить и к удобной цифре: это максимум по точкам съёма, между замерами могли быть всплески. То же ограничение я предъявлял к load average, и нечестно вспоминать про него только там, где оно снижает страшное число.

Это подтверждает то, что вы видели в июльском инциденте: очередь шины пустая, а канал стоит.

 

Шина или прямой REST

Все замеры выше про то, как шина живёт. Остался вопрос, зачем она вообще: не дешевле ли десять систем связать напрямую. Честного ответа у меня нет, есть только структура своего трафика.

В схемах есть и HTTP-узлы, и очереди. Через HTTP за месяц прошло 1 907 700 сообщений, и 1 891 016 из них - один обмен с CRM и программой лояльности. Архитектурного паттерна тут нет.

Поэтому вывод «команда осознанно развела HTTP и очереди по типам задач», который просился, я делать не буду: из процентов намерение не выводится, авторов схем я не спрашивал. Историческое наслоение объясняет картину ничуть не хуже. И «один из самых нагруженных обменов» тоже неверно: 1,89 миллиона против 10,0 миллиона у крупнейшего процесса - это в пять раз меньше.

Классификация сделана по именам узлов в метриках. Имена вроде FromHTTP однозначны, но десятки узлов с нейтральными именами по метрике не читаются. Разбивку всех 173 узлов по типам даёт только консоль, и эти десять минут я не потратил.

Что даёт очередь и чего она стоит

Критерий Очереди Прямой REST
Приёмник недоступен копятся, доставятся позже ошибка у отправителя, повтор пишете сами
Всплеск нагрузки (у нас 3,6×) сглаживается очередью приёмник принимает удар целиком
Гарантии доставки at-least-once, durable, подтверждения ровно то, что напишете
Переотправка после инцидента есть журнал доставленных, но только через UI только если храните исходящие сами
Связность отправитель не знает приёмника жёсткая: адрес, схема, версия
Один ко многим штатно отправлять N раз самому
Задержка выше: несколько узлов плюс брокер ниже: один вызов
Отладка сложнее: узлы, очереди, журналы проще: запрос и ответ
Стоимость эксплуатации высокая, см. всё выше низкая

Шина не убирает проблемы интеграции, она меняет их набор. Из моих четырёх сюжетов три специфичны именно для брокерной доставки: откат позиций при рестарте, очередь без потребителя, конкурирующий потребитель на одном участнике.

А вот четвёртый, «доставлено не равно загружено», при REST никуда не девается - там это ответ 200 до фиксации транзакции, и ловится он ровно так же, сверкой по идентификаторам. Я сначала написал, что при REST такого не бывает в принципе. Неправда: не бывает первых трёх, четвёртый остаётся.

Считать «оправдана ли шина» надо через часы сопровождения: сколько человеко-часов за год съели пять дефектов, три инцидента, самописный сервис автолечения, ночной cron и экспортёры, один из которых врал, - я не считал. Поэтому вместо критерия скажу как есть: мы остались на шине, потому что десять систем через прямые вызовы связывать дороже. Для двух систем и сотни запросов в сутки я бы её не ставил.

 

Про отказоустойчивость: добавлю один факт

Тема разобрана в июльской статье; добавлю то, что определяет всю конструкцию.

Системные хранилища Шины живут на встроенной H2, и вынести их во внешнюю СУБД нельзя. Проверено по конфигурации нашей установки 6.1.6.

Дальше идут выводы, и я помечаю их именно так. Два узла мы не разворачивали. Раз системные базы локальные, отказоустойчивость серверного слоя остаётся только через репликацию тома. Замок, не дающий регламентному заданию выполниться дважды, хранится в локальной H2 каждого узла - значит два активных узла выполнят каждое задание по два раза. Плюс конкурирующие потребители и риск split-brain, когда оба узла решат, что главные они.

Штатного режима, где несколько узлов работают как одна система, у продукта нет: руководство описывает один узел, а представитель вендора на профильной конференции этого года сказал, что реализовать это сложно и конкретных планов нет.

Реалистичный максимум - active-passive с виртуальным адресом и fencing, то есть гарантированным отключением отказавшего узла, внешний отказоустойчивый брокер как буфер, PostgreSQL под кластерным менеджером, идемпотентные приёмники. Горизонтальное масштабирование - функциональным шардингом: разные процессы на отдельные одноузловые экземпляры.

Контраргумент про запас: расти вертикально есть куда по процессору, 22 процента средней загрузки. Только процессор нас и не убивал. Запас надо считать по тому, что упирается - по памяти, inode, скорости восстановления журнала (у нас на большом журнале это девять минут, и идёт оно в один поток) и по H2, которую не разнести. Такого замера у меня нет.

 

Чеклист

Двадцать пунктов. Те, что разобраны выше, идут с отсылкой; остальные подтверждены практикой, но в тексте не раскрыты.

Развёртывание и рестарты

  1. stop_grace_period в Docker: дефолт десять секунд для брокера с большим журналом мал, мы поставили 300.
  2. Рестарт Шины не бесплатен для приёмников: откатывает позиции и может заклинить входящие очереди в 1С.
  3. Рестарт может обнулить хранилище доставленных, а это единственный источник для переотправки. Сначала переотправка, потом рестарт.
  4. Время старта плавает: штатно две минуты, около четырёх с половиной если стартовый скрипт контейнера (entrypoint) делает рекурсивный chown, до девяти если брокеру нужно восстановление большого журнала.
  5. Watchdog с коротким терпением убивает Шину посреди загрузки и уходит в петлю перезапусков. У нас это случилось.
  6. development-mode на проде роняет управляющий слой.
  7. Выключение режима разработки передеплоивает приложение и обнуляет счётчики метрик. Провал на графиках в этот момент не инцидент - и, если он попал в ваше окно замера, объёмы за это окно занижены.

Мониторинг

  1. Зонд обязан трогать управляющий слой. Корневой URL отдаёт 301, когда обмены уже стоят.
  2. Мониторить inode наравне с гигабайтами.
  3. Мониторить возраст старейшего сообщения наравне с длиной очереди.
  4. Пороговые алерты на поток не работают при суточном разбросе в десятки раз.
  5. Алерт «очередь без потребителя» фолзит на очередях, где потребителя нет by design. Строить на связке «есть остаток И нет потребителя».
  6. Правка правил алертинга через sed -i не применяется при bind-mount одного файла. Писать поверх.
  7. Верифицировать собственные метрики. Наша показывала inode вместо счётчика и питала боевой алерт.

Данные и доставка

  1. «Доставлено» на шине не равно «загружено» в приёмнике. Сверять end-to-end по идентификаторам.
  2. Идемпотентность приёмника обязательна. Модель доставки at-least-once, без дедупликации переотправка даст дубли документов.
  3. Окна хранения у шины и приёмника различаются на порядки.
  4. Переотправка только через UI консоли, публичного метода нет.
  5. Один участник шины - один потребитель. Второй подключившийся сеанс молча съест часть потока.
  6. Хранение доставленных включать точечно и временно, с напоминанием на выключение. На нагруженных каналах это 250 тысяч файлов в сутки, которые платформа не удалит.

 

Открытый вопрос

Мой тезис после года: в связке шина плюс 1С отказ чаще возникает на приёмнике - как застревание, а не нехватка пропускной способности. У меня одна установка, так что это наблюдение и на закономерность не тянет.

По какому раннему признаку вы отличаете «шина не успевает» от «приёмник встал»? К моменту, когда видно обе стороны, ответ уже очевиден.

И второй, для тех, кто мониторит возраст сообщений: вы считаете его от часов сервера мониторинга или от времени, которое отдаёт сама 1С? Мы перешли на время источника, но, возможно, есть решение красивее.

Другие наши инструменты диагностики 1С:

  • Карта объёмов базы 1С - из чего состоит база и куда ушли гигабайты. В этой истории пригодилась бы на стороне приёмника: регистры буфера обмена растут молча, а в списке самых тяжёлых таблиц видны сразу.
  • Чек-ап СУБД под 1С - 40 с лишним проверок настроек сервера СУБД под платформу. У нас под приложениями Шины живут 24 базы PostgreSQL, и настройки им достались по умолчанию.
  • Трансформатор SQL в запрос 1С - когда в плане запроса или в блокировке видно имя таблицы, а надо понять, какой объект конфигурации за ним стоит. Ровно та карта имён, которой не хватает, когда разбираешь затык во входящей очереди чужой базы.

Вступайте в нашу телеграмм-группу Инфостарт

1С:Шина ESB интеграция обмен данными ActiveMQ Artemis RabbitMQ брокер сообщений очереди Docker stop_grace_period Prometheus мониторинг inode идемпотентность буфер обмена 1С возраст сообщения отказоустойчивость PostgreSQL эксплуатация диагностика

Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».

  • 0% комиссии — оплата напрямую исполнителю;
  • Исполнители любого масштаба — от отдельных специалистов до команд под проект;
  • Прямой обмен контактами между заказчиком и исполнителем;
  • Безопасная сделка — при необходимости;
  • Рейтинги, кейсы и прозрачная система откликов.

См. также

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист 1С:Предприятие 8 1С:Комплексная автоматизация 1.х 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Платные (руб)

Перенос данных из 1С:Управление производственным предприятием 1.3 в 1С:Бухгалтерия предприятия 3.0 с помощью правил обмена | Можно выполнить переход с УПП на БП 3 или запускать выгрузку данных за выбранный период времени | Переносятся документы, начальные остатки и вся справочная информация | Есть фильтр по организации и множество других параметров выгрузки | Поддерживается несколько сценариев работы: как первичный полный перенос, так и перенос только новых документов | Перенос данных возможен в "1С: Бухгалтерия 3.0" версии ПРОФ, КОРП или базовую | Переход с "1С: УПП1.3" / "1С:КА 1.1" на "1С:БП3.0" с помощью правил конвертации будет максимально комфортным! | Можно бесплатно проверить перенос на вашем сервере!

50050 руб.

25.02.2015    190843    372    294    

428

Перенос данных 1C Программист 1С:Предприятие 8 1С:Управление производственным предприятием 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос документов, начальных остатков и справочной информации из УПП 1.3 в ERP 2 | из УПП 1.3 в УТ 11 | из УПП в КА 2 | Правила конвертации (КД 2) | Более 360 предприятий выполнили переход с использованием этого продукта! | Сэкономьте время - используйте готовое решение для перехода! | Позволяет перенести из УПП 1.3 в ERP / УТ 11 / КА 2 всю возможную информацию | В переносе есть фильтр по организации и множество других опциональных параметров выгрузки | Есть несколько алгоритмов выгрузки остатков на выбор

58000 руб.

04.08.2015    192448    462    308    

462

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист 1С:Предприятие 8 1С:Розница 2 1С:Управление нашей фирмой 1.6 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Розница 3.0 Россия Платные (руб)

Правила в универсальном формате обмена для ERP 2.5, КА 2.5, УТ 11.5, БП 3.0, Розница, УНФ, для последних версий конфигураций. Ссылки на другие конфигурации в описании публикации. Правила совместимы со всеми другими версиями конфигураций новыми и старыми, поддерживающими обмен и синхронизацию в формате EnterpriseData. Не требуется синхронного обновления правил после обновления другой конфигурации, участвующей в обмене. Типовой обмен через планы обмена кнопкой Синхронизация вручную или автоматически по расписанию, или вручную обработкой.

27633 24870 руб.

12.06.2017    163264    993    329    

487

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Платные (руб)

Перенос данных из ERP в БП 3 | из КА 2 в БП 3 | из УТ 11 в БП 3 | из ЕРП в БП 3 | Сэкономьте время - используйте готовое решение для перехода! | Перенос разработан в формате КД 2 (правила конвертации данных) | Переносятся все возможные виды документов, начальных остатков и нормативно-справочная информация| Можно опционально выгружать каждую пару "номенклатура+характеристика" как отдельную номенклатуру | Есть выгрузка настроек счетов учета и зарплатных данных из ERP / КА 2 | Можно проверить на вашем сервере перед покупкой

58000 руб.

15.04.2019    86203    231    181    

168

Перенос данных 1C Взаиморасчеты Оптовая торговля Логистика, склад и ТМЦ Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист 1С:Предприятие 8 1С:Управление торговлей 10 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Управленческий учет Платные (руб)

Можно проверить до покупки, оставьте заявку! Воспользовались более 268 компаний! Перенос данных из УТ 10.3 в УТ 11 | из УТ 10.3 в КА 2 | из УТ 10.3 в ERP. Решение для перехода с УТ 10.3. Можно перенести начальные остатки, нормативно-справочную информацию и все возможные документы. При выгрузке можно установить отбор по периоду, организациям и складам.

50200 руб.

24.04.2015    209539    179    253    

298

SALE! 10%

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Системный администратор Программист 1С:Предприятие 8 1С:Управление производственным предприятием 1С:Бухгалтерия 3.0 Россия Бухгалтерский учет Управленческий учет Платные (руб)

Переносите справочную информацию, остатки и документы из УПП 1.3 в Бухгалтерию 3.0 с помощью готовых правил. Переносится более 50 видов документов. Простой интерфейс и понятные настройки.

42000 37800 руб.

15.12.2021    35726    263    68    

200

Перенос данных 1C Файловый обмен (TXT, XML, DBF), FTP Программист 1С:Предприятие 8 1С:ERP Управление предприятием 2 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Россия Бухгалтерский учет Управленческий учет Платные (руб)

Перенос данных из ERP в ЗУП 3 | из КА 2 в ЗУП | Готовые правила конвертации данных (КД 2) для переноса остатков, документов с движениями и справочной информации 3 | Есть перенос начальной задолженности по зарплате и начальной штатной расстановки на выбранную дату | Обороты за прошлые годы (данные для расчета среднего) переносятся свернуто в документ "Перенос данных" | Есть фильтр по организациям | Документы за текущий период переносятся сразу с движениями, поэтому не потребуется делать перерасчеты | Перенос можно проверить перед покупкой, обращайтесь!

55200 руб.

03.12.2020    46376    132    83    

122

Работа с интерфейсом Анализ учета Мониторинг 1С:Предприятие 8 1С 8.3 1C:Бухгалтерия 1С:Бухгалтерия 3.0 1С:ERP Управление предприятием 2 1С:Управление холдингом 1С:Зарплата и Управление Персоналом 3.x 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 1С:Управление торговлей 11 Платные (руб)

Создайте свой функциональный интерфейс в любой конфигурации 1С с помощью расширения Infostart Dashboard. Настраивайте панели виджетов с метриками, индикаторами и показателями на начальном экране. Узнайте возможность внедрения подсистемы у себя в конфигурации с помощью бесплатной обработки "Анализ внедрения подсистемы 1С Infostart Dashboard"!

31720 руб.

27.03.2025    89503    67    44    

75
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. gybson 13 17.08.26 19:45 Сейчас в теме
Просто все временные метки должны быть зафиксированы на каждом этапе. Возникновение события - обработка события - отправка события - получение события - обработка полученного события - возникновение результата обработки события. Застревание в приемнике это баг архитектуры. Приемник принимает, записывает и потом обрабатывает. Разный уровень - разная ответственность. Шина не должна отвечать за обработку сообщения на стороне приемника, только за доставку.
PavelT_057; nedomolkov.ivan; +2 Ответить
2. nedomolkov.ivan 164 18.08.26 05:27 Сейчас в теме
(1)
Просто все временные метки должны быть зафиксированы на каждом этапе. Возникновение события - обработка события - отправка события - получение события - обработка полученного события - возникновение результата обработки события. Застревание в приемнике это баг архитектуры. Приемник принимает, записывает и потом обрабатывает. Разный уровень - разная ответственность. Шина не должна отвечать за обработку сообщения на стороне приемника, только за доставку.


Так и сделано: приёмник сперва пишет в регистр-буфер, разбор отдельно. И всё равно встало.

Причём буфер был пустой. Отставание 31 час, а сообщений в нём нет, значит затык не в обработке,
а раньше. Был и такой случай: после рестарта шина откатывает позиции, 1С видит номер,
который уже считает обработанным, и FIFO-очередь клинит на первой коллизии.

Метки поддерживаю, только они лежат в разных местах и с разным сроком: на шине 6 часов,
в регистре 14 дней. Разбираешься на следующий день, а половины цепочки уже нет.

Про доставку в точку. Раз шина за обработку не отвечает, она это и не покажет: у нас
61 недоставленное на 26 миллионов, цифра красивая и мимо. Смотреть надо у приёмника,
на возраст самой старой необработанной записи. Длина очереди тогда была зелёная.

А вы метки в одно место складываете или сшиваете потом по идентификатору?
3. gybson 13 18.08.26 09:00 Сейчас в теме
(2) у нас эксплуатируют другие люди, не программисты :) и проблемы будут всегда и может быть даже каждый день, поэтому необходимо чтобы под рукой у поддержки были средства эксплуатации. Например сделали скан договора на 500Гб (утрирую, но могут) и обмен встал. И если observability реализовано хорошо, то это сразу видно. Если плохо, то надо звать технарей, которые куда-то полезут, будут проверять. На живой системе миллион проблем и решаются они только построением системы эксплуатации.
4. nedomolkov.ivan 164 18.08.26 09:10 Сейчас в теме
(3) Согласен. Добавлю только, что плохой мониторинг хуже никакого: у нас панель показывала
3,8 миллиона ошибок, которых не было. Через неделю поддержка на красное просто не смотрит
и настоящую поломку пролистывает

И для известных поломок панель уже не нужна, нужен робот. Клин очередей после рестарта мы
на дашборд не вынесли, написали сервис: обходит очереди раз в минуту, за 30 дней сработал
22 раза, никого будить не пришлось. Панель нужна для того, чего мы ещё не видели.

Ваш скан на 500 Гб дежурный поймает по возрасту самой старой необработанной записи.
Длина очереди при этом зелёная.
Для отправки сообщения требуется регистрация/авторизация