Счётчики не отвечают на вопрос
Когда база начинает тормозить, админ открывает консоль кластера и видит таблицу метрик. Сеансов столько-то, память такая-то, процессорное время, вызовы, соединения. Всё это правда, но это не ответ. Ответ звучит иначе: "с двух до четырёх ночи базу держал регламентный обмен, а утром её добил отчёт, который запустил конкретный человек".
Между таблицей счётчиков и этим ответом лежит работа, которую админ каждый раз делает в голове: сопоставить номера сеансов, вспомнить, кто под каким работает, сложить пики во времени. Инструменты мониторинга обычно отдают сырьё и оставляют эту работу вам. А работа эта повторяется каждый раз, когда кто-то жалуется на тормоза, и каждый раз отнимает те же двадцать минут.
В этой статье я разберу другой подход к мониторингу нагрузки кластера 1С: не показывать счётчики, а отвечать на человеческие вопросы. И разберу технику, без которой такой подход не работает, потому что дьявол тут в деталях хранения и в поведении кластера за балансировщиком.
Подход: вопрос вместо метрики
Идея простая. Вместо таблицы счётчиков дать список вопросов человеческим языком, и на каждый нарисовать готовый ответ с именами людей. Пользователь выбирает вопрос из списка, задаёт период и получает диаграмму, где самая длинная полоса и есть главный виновник. Складывать числа глазами не нужно.
Ключевое отличие от типовых мониторингов: они отвечают "кто держит базу сейчас", а правильный вопрос почти всегда в прошедшем времени. Не "кто блокирует прямо в эту секунду", а "кто держал базу с двух до четырёх ночи, когда всё встало". Мгновенный снимок этого не покажет, нужна история.
Семь вопросов, на которые стоит уметь отвечать
Кто блокировал базу. Главный вопрос. Источник это поля снимка с номером сеанса, который платформа называет блокирующим по СУБД или по управляемым блокировкам. По номеру из того же снимка достаётся имя пользователя, компьютер и приложение держателя. Диаграмма это горизонтальные полосы по держателям, отсортированные по суммарному времени в роли того, кто держал. Важная тонкость: в выборку надо сохранять и жертву, и держателя, иначе на вопрос "кто держал" ответить нечем, останутся только пострадавшие.
Кто грузит сервер. Процессорное время за пятиминутку, свёрнутое по пользователю. Здесь важна честность: показываем ряд за период, а не один замер. Разовый пик не делает человека виноватым, а вот стабильно высокая полоса по всему дню это уже разговор.
Кто ест память. Потребление памяти сеансами. Тут есть ловушка агрегации: память нельзя суммировать по замерам, иначе число растёт от частоты съёма, а не от аппетита сеанса. Правильно брать максимум за период. Отдельно интересны сеансы, у которых память растёт монотонно замер за замером, это кандидат на утечку.
Кто больше всех захватывает СУБД. Отдельно от общей нагрузки. Бывает, что человек почти не потребляет процессор, но держит СУБД. Источник это длительность вызовов СУБД и объём переданных данных, свёрнутые по пользователю. Высокая доля СУБД при низком процессорном времени это признак тяжёлого запроса или ожидания на блокировке, а не жадного клиента, и вопрос "кто грузит сервер" такого не разделяет.
Куда уходят лицензии. Сколько клиентских мест занято во времени и в какие моменты упирались в потолок. Тут своя ловушка: считать надо только клиентские места, держателем которых является сеанс. Серверный ключ держит рабочий процесс, у него мест бывает одно, и без отбора тревога горит круглосуточно на ровном месте.
Что было ночью. Временной ряд по базе целиком за период: сеансы, соединения, вызовы, заблокированные по СУБД и по сервису блокировок, память процессов. Несколько линий на общей оси времени, где видно и ночной провал, и утренний пик, и то самое окно, где было хуже всего.
Кто спит и держит место. Спящие сеансы: кто, с какого времени и держит ли лицензию. Человек ушёл домой, не закрыл клиент, и его сеанс продолжает занимать место.
Список открытый. Правильно описывать вопрос данными, а не отдельной процедурой на каждый случай. Тогда новый вопрос добавляется одной строкой, а разбор и отрисовка остаются общими. Иначе список из восьми вопросов превращается в восемь копий одного кода, и девятый вопрос стоит столько же, сколько первый.
Откуда брать данные
Штатный объект платформы АдминистрированиеСервера, доступный с 8.3.14. Он отдаёт кластеры, информационные базы, рабочие процессы, сеансы и соединения со всеми счётчиками: процессорное время за пять минут, потребление памяти текущее и всего, длительность и количество вызовов, длительность вызовов СУБД, номер блокирующего сеанса, признак спящего сеанса, лицензии.
Никакого rac.exe, никакого запуска внешних приложений, никакого COM. И, что важно для универсальности, к самой СУБД обращаться не нужно вообще, как и к прикладным объектам конфигурации. Обработка, построенная на этом объекте, работает с любой конфигурацией, потому что не знает и не хочет знать, что за документы и справочники внутри базы.
Минимальная поддерживаемая версия платформы это 8.3.14, когда объект появился. Проверять работоспособность стоит и на более старых ветках вроде 8.3.20, это типичная платформа у многих клиентов, и на свежих вроде 8.3.27.
Главная ловушка исторического мониторинга: объём
Если писать историю нагрузки, первым же встаёт вопрос размера. Наивный подход, запись каждого сеанса на каждом замере, на активном кластере за сутки набивает сотни мегабайт. Хранить это негде, читать долго, толку ноль.
Решение: зерном снимка делать не сеанс, а агрегат по базе плюс топ сеансов по каждому показателю. То есть на каждый замер по базе пишется сводка (сколько сеансов, сколько заблокировано, суммарная память, процессор, вызовы, лицензии) плюс, скажем, топ двадцать сеансов по каждой метрике, объединённых без повторов. И отдельно, полностью, сохраняются те немногие сеансы, что попали в событие: держатель блокировки и его жертвы. Их мало, а именно они нужны для ответа на главный вопрос.
Хранить это удобно файлами на диске сервера, по строке JSON на снимок, с раскладкой по папкам суток и баз. Дозапись в конец файла, перечитывать ничего не надо. Отбор по периоду тогда делается перебором папок дат, лишние файлы даже не открываются: за неделю открываются семь папок, остальные не трогаются. В каждой строке стоит номер версии схемы, чтобы формат можно было развивать. Ротация по кольцу: удаление папок старше заданной глубины плюс потолок по объёму.
Кластер из нескольких серверов ломает наивное хранение
Вот тут начинается то, что вылезает только на настоящем проде. Если сервер 1С состоит из нескольких рабочих серверов (кластер за балансировщиком, строка соединения вида два-три хоста через запятую), то узлы кластера не делят файловую систему. Каталог C:\ProgramData на узле номер один и такой же путь на узле номер два это разные каталоги на разных машинах.
Последствие жестокое. Регламентное задание сбора отработает на том узле, который в этот момент свободен. Один снимок ляжет на узел один, следующий на узел два. А форма, когда вы её откроете, прочитает историю с того узла, куда попал ваш сеанс. В итоге история размазана по узлам и никогда не собирается в одну картину, и выглядит это как "данные то есть, то нет".
Лечение: каталог истории должен быть сетевой папкой, доступной всем узлам кластера на запись под учётной записью службы сервера 1С. Тогда все узлы, и регламент, и форма, пишут и читают одно место. Это не костыль, а единственно правильная схема для многоузлового кластера, и инструмент обязан о ней прямо предупреждать, а не молчать, пока пользователь час гадает, почему пусто.
Настройки должны доходить от формы до регламента
Ещё одна грабля того же класса. Настройки (адрес RAS, каталог, учётка кластера) пользователь задаёт в форме. Регламентное задание работает без формы вообще и должно взять те же настройки. Казалось бы, положи в общее хранилище настроек и всё.
Но хранилище общих настроек привязывает записи к пользователю. Форма сохраняет под интерактивным пользователем, а регламентное задание выполняется под служебной учёткой и настроек формы не видит. Оно откатывается на умолчания и пишет не туда либо не пишет вовсе. Решение: сохранять и читать под одним фиксированным псевдо-пользователем, тогда обе стороны видят одну запись независимо от того, под кем выполняются. И, что важно на кластере, хранилище лежит в базе, общей для всех узлов, в отличие от файла, который на узлах не делится, так что для настроек это правильное место, а для истории нет.
Как обработка понимает, в какой базе она запущена
Инструмент должен работать с той базой, где открыт, без выбора из списка на сотню баз кластера. Обычный способ, разбор строки соединения информационной базы и вытаскивание имени базы из параметра Ref, работает не всегда: на кластере с резервированием серверная строка соединения не всегда содержит Ref в ожидаемом виде.
Надёжный запасной способ: найти собственный сеанс среди сеансов кластера. У обработки есть номер своего сеанса и имя пользователя, а у каждого сеанса кластера есть идентификатор информационной базы. Находим свой сеанс по паре номер плюс пользователь, берём идентификатор его базы, сопоставляем со списком баз кластера, получаем имя. Работает на любом кластере, включая балансировщик. Важно только не делать это тяжёлой операцией на каждом открытии формы: определили один раз, запомнили в настройках, дальше берём из кэша мгновенно.
RAS: поднять один раз
Обработка подключается к серверу администрирования (RAS), но не обязана его поднимать. Если RAS уже работает, она просто подключается. Если нет, службу RAS ставят один раз, и это единственная операция, требующая прав администратора, потому что создание службы Windows это ограничение самой ОС.
Тонкость, которая стоит нервов: версия RAS должна совпадать с версией сервера. Если на машине несколько версий платформы (обычное дело после обновления) и поднять RAS свежей версии против агента старой, подключение ответит "различаются версии клиента и сервера". Правильно брать ras.exe из каталога работающего агента кластера, а не самый свежий из установленных. Определяется это по пути службы агента, а не по процессу, у служебных процессов путь через WMI часто пуст.
Обезличивание для отчётов и скриншотов
Имена пользователей и компьютеров это персональные данные. Когда результат уходит наружу (скриншот в статью, отчёт руководителю, картинка в карточку решения), их надо маскировать. Причём маскировать на входе, стабильно: один и тот же реальный человек должен всегда получать один и тот же псевдоним, иначе в ряду по времени он размажется на несколько разных полос. Детерминированный псевдоним по хешу имени решает это, а сама история на диске при этом остаётся реальной, обезличивание только на показе.
Чего такой инструмент не заменяет
Честная граница важнее длинного списка возможностей. Разбор технологического журнала это отдельная тема с отдельным парсером и отдельной тяжестью, и там есть более сильные специализированные решения. Разбор журнала регистрации это другой источник. Толкать метрики во внешний стек мониторинга отдельная задача, аудитория 1С внешний стек держит редко. Управление кластером (убить сеанс, заблокировать соединения) это отдельная ниша. Здесь речь именно про исторический анализ нагрузки штатными средствами платформы, и эту задачу, посмотреть что происходит в базе прямо сейчас и что было ночью, он закрывает целиком.
Готовый инструмент
Всё описанное собрано во внешней обработке "Анализ нагрузки кластера 1С". Она универсальная, сама определяет базу и кластер, проверяет доступ тремя шагами со светофором (служба RAS, доступ к кластеру, каталог истории), собирает историю регламентным заданием и рисует ответы родными диаграммами. Отдельная кнопка выгружает срез в Markdown, чтобы вставить в чат с ИИ и получить разбор. В комплекте лежит bat-файл, который поднимает службу RAS сам, если её ещё нет. Скачать её можно на карточке обработки.
Вступайте в нашу телеграмм-группу Инфостарт