· 14 мин чтения

Мониторинг сервера 1С:Предприятие через Zabbix: сеансы, блокировки СУБД, производительность кластера

Каждый второй звонок «1С зависла» на самом деле означает одно из трёх: сервер приложений упёрся в лимит рабочих процессов, СУБД держит блокировку дольше, чем терпит пользователь, или у кластера кончились лицензии сеансов. Обычный мониторинг «сервер жив, диск не полон, CPU в норме» ничего из этого не видит — потому что смотрит не в те метрики. За два года мы довели до продакшена собственную схему мониторинга 1С в Zabbix 7.0 LTS на нескольких клиентских инсталляциях (от связки MS SQL Server до PostgreSQL 15) и в этой статье показываю её целиком: какие шаблоны, какие ключи, какие пороги и почему.

Почему стандартный мониторинг сервера не ловит зависшую 1С

Классический набор триггеров на сервере приложений 1С — это CPU, RAM, свободное место на диске и доступность порта 1541 (кластерный менеджер) или 1560 (менеджер лицензирования). Этого достаточно, чтобы понять, что процесс жив, но совершенно недостаточно, чтобы понять, что пользователи работать не могут. Кластер 1С:Предприятие 8.3 может показывать 20% CPU и 40% RAM и при этом держать 200 сеансов в ожидании снятия блокировки строки в регистре накопления — потому что узкое место не в железе, а в логике конкуренции за ресурс СУБД или в конфигурации самого кластера (rphost, rmngr, ragent).

Мы регулярно видим три сценария, которые «зелёный» дашборд CPU/RAM пропускает полностью. Первый — управляемая блокировка 1С (объект УправляемаяБлокировка) висит внутри длинной транзакции проведения документа, и следующие 15 пользователей встают в очередь молча, без единой ошибки в журнале Windows. Второй — исчерпан лимит лицензий сервера (счётчик сеансов у клиента с временными лицензиями), и новые сеансы просто не открываются, а старые работают штатно, поэтому CPU/RAM спокойны. Третий — блокировка на уровне СУБД (row lock, page lock, эскалация до table lock в MS SQL, или конфликт ROW SHARE/ROW EXCLUSIVE в PostgreSQL) держит транзакцию проведения дольше секундного порога, заданного в настройках информационной базы (свойство «Устанавливать блокировку СУБД перед записью» и таймаут ожидания блокировки).

Наш вывод простой: мониторинг 1С должен идти из трёх источников одновременно — операционная система, административный сервер кластера 1С (RAS/RAC) и СУБД через DMV/pg_stat_activity. Ниже — как мы собираем всё это в единый набор триггеров Zabbix.

Наша трёхуровневая модель мониторинга кластера 1С в Zabbix 7.0

Мы разносим метрики по трём слоям и в каждом заводим отдельный шаблон в Zabbix, а не пытаемся впихнуть всё в один универсальный. Это упрощает наследование: сервер приложений 1С получает шаблон уровня ОС + шаблон уровня кластера, а сервер СУБД — шаблон уровня ОС + шаблон СУБД (MS SQL или PostgreSQL). Схема ниже — то, с чем мы заходим к клиенту в первый день внедрения.

УровеньЧто контролируемИсточник данных в ZabbixКлючевой item
ОС / сервер приложенийCPU, RAM, диск, доступность портов 1540-1541, 1560, 1545 (ras)Zabbix agent2, net.tcp.servicenet.tcp.service[tcp,,1541]
Кластер 1С (RAS/RAC)число сеансов, число рабочих процессов rphost, использование лицензий, зависшие соединенияUserParameter поверх утилиты rac, вызываемой к службе rasonec.sessions.count[*], onec.licenses.used[*]
СУБДактивные блокировки, длительность ожидания, топ-запросы по CPU/IO, размер tempdb / bloat таблицTemplate DB MSSQL by ODBC / PostgreSQL by Zabbix agent 2db.odbc.get[...], pgsql.locks

Важный нюанс: слой «Кластер 1С» у нас не встроенный шаблон из официального репозитория Zabbix (готового шаблона под RAS/RAC в маркетплейсе Zabbix нет) — это наша собственная обвязка через UserParameter и парсинг вывода rac. Слой СУБД, наоборот, мы стараемся не изобретать — берём готовые шаблоны «MSSQL by ODBC» и «PostgreSQL by Zabbix agent 2» из официального репозитория шаблонов Zabbix 7.0 и донастраиваем макросы под конкретную инсталляцию.

Разворачиваем связку: Zabbix agent2, служба RAS и утилита rac

Административный сервер кластера 1С (ras) — это отдельная служба, которая должна быть поднята рядом с рабочим процессом кластера (обычно на том же хосте, что и ragent). По умолчанию она слушает TCP 1545. Мы разворачиваем её как windows-службу (или systemd-unit на Linux-сервере 1С) командой вида:

ras cluster --daemon --port=1545 localhost:1540

После этого весь мониторинг кластера идёт через утилиту-клиент rac, которая обращается к ras по протоколу IIOP. Список кластеров, список информационных баз и список сеансов мы получаем так:

rac cluster list
rac infobase summary list --cluster=<UUID_кластера> localhost:1545 --cluster-user=zbx_mon --cluster-pwd=<пароль>
rac session list --cluster=<UUID_кластера> localhost:1545 --cluster-user=zbx_mon --cluster-pwd=<пароль>

Дальше мы оборачиваем это в UserParameter агента Zabbix 7.0 (agent2, конфиг zabbix_agent2.conf или отдельный файл в zabbix_agent2.d/). Формат UserParameter в 7.0 не изменился — UserParameter=<ключ>,<shell-команда>, флексибл-параметры принимают позиционные $1, $2 и так далее:

UserParameter=onec.sessions.count[*],/opt/1cv8/x86_64/8.3.24.1234/rac session list --cluster=$1 $2:1545 --cluster-user=$3 --cluster-pwd=$4 | grep -c "^session"

Это наш собственный скрипт-обвязка, не часть официальной поставки — мы держим его в /etc/zabbix/scripts/onec_rac.sh и вызываем из UserParameter, чтобы не городить парсинг прямо в конфиге. Учётку zbx_mon заводим в кластере отдельно, с правами только на чтение (администратор кластера без прав на изменение сеансов) — это снижает риск, что мониторинговый скрипт случайно завершит чужой сеанс.

Для служб ras/ragent отдельно добавляем стандартную проверку доступности порта средствами самого agent2 — без внешних скриптов: net.tcp.service[tcp,,1545] и net.tcp.service[tcp,,1541]. Если порт не отвечает, весь остальной сбор через rac бессмысленен, поэтому этот item мы делаем master-item с зависимыми триггерами через dependent items, чтобы не заваливать очередь алертами «rac timeout» при обычной перезагрузке кластера.

Сеансы и лицензии: где чаще всего рвётся работа бухгалтерии

Отдельная головная боль клиентов на клиент-серверном варианте — исчерпание лицензий. Кластер лицензирует сеансы через программный ключ (HASP) или через 1С:Лицензирование (soft-лицензии), и когда лимит выбран, новые сеансы не открываются вообще, при этом старые пользователи продолжают работать и жалоб от них нет — жалуется тот, кто только пытается зайти утром, когда все уже подключились. Мы вытягиваем состояние лицензий отдельным вызовом:

rac session list --licenses --cluster=<UUID> localhost:1545 --cluster-user=zbx_mon --cluster-pwd=<пароль>

Из вывода парсим количество активных сеансов с выданной лицензией и сравниваем с лимитом, зашитым в HASP-ключ клиента (это число мы один раз узнаём у клиента через утилиту диагностики HASP или через 1С:Предприятие → Администрирование → Активные пользователи и заносим в макрос шаблона {$ONEC.LICENSE.LIMIT}). Порог тревоги мы ставим на 90% от лимита — по нашей практике именно на этом уровне начинают появляться первые отказы «нет доступной лицензии» у случайных пользователей, а не у всех сразу.

Второй момент — «зависшие» сеансы: пользователь закрыл клиент через диспетчер задач, а сеанс на сервере остался открытым и держит лицензию до истечения таймаута. Мы отслеживаем возраст сеанса без активности через поле sessionhibernate и last-active-at в выводе rac session info, и если сеанс висит в hibernate дольше заданного нами порога (по практике — 4 часа для обычного офиса, для 1С:Розница на кассах — 15 минут), заводим триггер «зависший сеанс без лицензии» с рекомендацией на принудительное завершение через rac session terminate.

Блокировки СУБД: MS SQL Server — DMV, которые мы реально используем

Когда клиент на связке 1С + MS SQL Server жалуется «зависла проводка», в 90% случаев причина — блокировка на уровне СУБД, а не кластера 1С. Мы собираем это через шаблон MSSQL by ODBC из официального репозитория Zabbix (требует установленного ODBC-драйвера Microsoft на сервере Zabbix или прокси, макрос {$MSSQL.DSN} указывает на DSN подключения) и добавляем собственные items поверх типового item db.odbc.get с прямым SQL-запросом к DMV.

Базовый запрос, который у нас идёт каждую минуту:

SELECT r.session_id, r.blocking_session_id, r.wait_type, r.wait_time, r.status, t.text FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE r.blocking_session_id <> 0

Столбец blocking_session_id в sys.dm_exec_requests прямо показывает, какая сессия блокирует текущий запрос — не нужно ничего вычислять руками. Если нужна детализация по типу лока (какой конкретно ресурс — строка, страница, таблица), мы дополняем запросом к sys.dm_tran_locks, соединяя его с sys.dm_os_waiting_tasks по адресу владельца лока. Для выполнения запросов к этим DMV учётной записи мониторинга нужна серверная роль с разрешением VIEW SERVER STATE (для более новых билдов SQL Server, где часть DMV вынесена в отдельное разрешение VIEW SERVER PERFORMANCE STATE — это стоит проверять на конкретной версии клиента, единого правила «до/после версии X» мы не фиксируем как гарантированный факт, только как практическое наблюдение).

Порог для триггера мы ставим не по количеству блокировок (оно почти всегда >0 в рабочее время — это нормально для 1С с построчными блокировками), а по длительности ожидания: если wait_time у заблокированного запроса превышает 30 секунд — предупреждение, если превышает 120 секунд — авария. Именно 120 секунд у нас коррелирует с моментом, когда у пользователя в клиенте 1С выскакивает стандартное сообщение о превышении времени ожидания блокировки.

Блокировки СУБД: PostgreSQL — pg_stat_activity и pg_locks

На связке 1С + PostgreSQL (например, PostgreSQL 15/16 из дистрибутива 1С — 1C-совместимая сборка postgrespro или ванильный PostgreSQL с патчами для 1С) логика та же, но инструментарий другой. Официальный шаблон PostgreSQL by Zabbix agent 2 (доступен из коробки в Zabbix 7.0, работает через встроенный плагин postgres агента agent2, макросы {$PG.HOST}, {$PG.PORT}, {$PG.USER}, {$PG.PASSWORD}, {$PG.DB}) закрывает общую статистику (соединения, коммиты, кэш-хиты), но конкретные блокировки под 1С мы вытягиваем отдельным item поверх pgsql.query.count или собственного скрипта с прямым SQL:

SELECT pid, pg_blocking_pids(pid) AS blocked_by, wait_event_type, wait_event, state, query FROM pg_stat_activity WHERE wait_event_type = 'Lock'

Функция pg_blocking_pids(pid) возвращает массив PID процессов, которые блокируют указанный процесс — удобнее, чем вручную джойнить pg_locks сам на себя по relation и transactionid. Для детального разбора «кто именно держит блокировку и на каком объекте» мы всё же джойним pg_locks с pg_stat_activity по pid, чтобы получить имя отношения (pg_locks.relation::regclass) — это критично для 1С, потому что даёт понять, какая именно таблица регистра или документа стала узким местом.

Отдельно отслеживаем автовакуум: если долгая блокирующая транзакция мешает автовакууму пройти по большой таблице движений регистра, начинается разрастание (bloat), и через пару недель без вмешательства СУБД начинает деградировать по производительности независимо от блокировок текущего дня. Мы заводим item на возраст самой старой активной транзакции (now() - xact_start из pg_stat_activity) с порогом предупреждения 10 минут — по нашей практике именно долгие открытые транзакции 1С (например, зависшая фоновая регламентная задача) чаще всего блокируют автовакуум.

Хотите видеть проблему 1С раньше, чем её увидят бухгалтеры

Мы разворачиваем эту трёхуровневую схему мониторинга — ОС, кластер 1С через RAS/RAC, блокировки СУБД — под ключ на вашей инфраструктуре: от установки Zabbix agent2 до калибровки порогов под вашу реальную нагрузку. Обычно это занимает 2-3 рабочих дня и не требует остановки продуктивной базы.

Пороговые значения триггеров, которые мы фактически используем

Собрали в одну таблицу пороги, с которыми выходим к клиентам после нескольких итераций — они откалиброваны по практике на нескольких инсталляциях 1С:Бухгалтерия/1С:ERP/1С:Розница с 15-60 пользователями, не универсальны для любых нагрузок, но это рабочая отправная точка.

МетрикаWarningHigh/DisasterКомментарий (оценка по практике)
Занятость лицензий кластера≥ 90% от лимита HASP≥ 98%На 90% начинают появляться единичные отказы новым пользователям
Возраст сеанса в hibernate без активности> 4 часа (офис) / > 15 мин (касса)> 12 часовДержит лицензию впустую, кандидат на принудительное завершение
Длительность блокировки MS SQL (wait_time)> 30 сек> 120 сек120 сек — порог, после которого клиент 1С обычно уже показал пользователю ошибку
Возраст открытой транзакции PostgreSQL> 5 минут> 10 минутБлокирует автовакуум, риск bloat таблиц движений
Число рабочих процессов rphost на кластер≥ 80% от max-memory-size в суммеисчерпание, kill-by-memoryСмотрим совокупно, не по одному процессу — кластер сам балансирует
Доступность ras (порт 1545)недоступен > 60 секMaster-item, от него зависят все rac-based триггеры (dependent items)

Все пороги мы делаем настраиваемыми макросами шаблона ({$ONEC.LICENSE.WARN}, {$MSSQL.LOCK.CRIT.WAIT}), а не хардкодим в триггере — потому что у клиента с 15 пользователями и у клиента с 60 пользователями «нормальная» длительность блокировки на пиковой нагрузке (например, закрытие месяца) объективно разная, и подгонка под конкретную инсталляцию занимает у нас обычно неделю наблюдений после первого включения.

Кейс: как мы ловим ситуацию «накладную провести нельзя» до звонка клиента

Показательный сценарий с одной из наших инсталляций клиент-сервер (1С:ERP на MS SQL Server, около 40 одновременных пользователей): раз в квартал, в первые дни закрытия периода, начинались массовые жалобы «зависает при проведении реализации». По логам Windows Event Log — ничего, CPU сервера приложений 35-40%, RAM в норме. Классический мониторинг ничего не показывал.

После того как мы включили слой блокировок СУБД, стало видно: регламентное задание пересчёта себестоимости запускалось в рабочее время (по расписанию, заданному ещё при внедрении несколько лет назад) и держало эксклюзивную блокировку на таблицу движений регистра накопления «Себестоимость товаров» на 8-12 минут. Всё это время любая проводка документа, затрагивающего себестоимость, вставала в очередь на blocking_session_id этого регламентного задания. Триггер «длительность блокировки MS SQL > 120 сек» сработал за 25 минут до первого звонка от бухгалтерии — этого хватило, чтобы среагировать проактивно: мы просто перенесли расписание регламентного задания на ночное окно и добавили отдельный триггер на длительность выполнения самого задания через RAC (сравнение фактического времени с историческим p95).

Без слоя блокировок СУБД эта проблема воспроизводилась бы раз в квартал ещё несколько лет — она не системная (не деградация железа), а организационная (неправильное окно регламентного задания), и её видно только через DMV, а не через метрики ОС.

Пошаговый план внедрения: 3 дня от нуля до рабочих триггеров

Порядок, которого мы придерживаемся у клиентов до 50 рабочих мест — сознательно компактный, без лишней теории:

  1. День 1, утро. Разворачиваем Zabbix agent2 на сервере приложений 1С и на сервере СУБД (если это разные хосты). Настраиваем базовые items ОС: CPU, RAM, диск, net.tcp.service на порты 1541/1545/1560.
  2. День 1, вечер. Поднимаем службу ras рядом с ragent, заводим отдельную учётную запись администратора кластера zbx_mon только на чтение. Проверяем вручную вызовы rac cluster list и rac session list с сервера Zabbix.
  3. День 2, утро. Пишем и кладём на сервер скрипт-обвязку под rac, регистрируем UserParameter в zabbix_agent2.d/onec.conf, перезапускаем службу агента, проверяем получение данных через zabbix_get.
  4. День 2, вечер. Импортируем официальный шаблон СУБД (MSSQL by ODBC или PostgreSQL by Zabbix agent 2), настраиваем макросы подключения, добавляем свои items с DMV/pg_stat_activity запросами поверх типовых item-ключей.
  5. День 3. Настраиваем триггеры с макросами порогов (без хардкода), временно ставим все триггеры в severity Warning (не Disaster), чтобы неделю понаблюдать за реальными значениями без ложных эскалаций, и только после калибровки поднимаем severity до боевых значений.
  6. Через 1-2 недели. Пересматриваем пороги по факту (обычно двигаем на 15-20% от первоначальных) и подключаем эскалацию — у нас это связка Zabbix → Telegram-бот с раздельными чатами для «предупреждение» и «авария», чтобы дежурный инженер не терял критичные алерты в потоке информационных.

Отдельно подчёркиваю: включение мониторинга блокировок СУБД не требует изменения кода 1С или доработки конфигурации — вся связка работает поверх стандартных механизмов платформы (RAS/RAC) и стандартных системных представлений СУБД, без установки чего-либо внутрь базы 1С.

Частые вопросы

Обязательно ли поднимать отдельную службу RAS, если у нас уже работает кластер 1С?
Да, ras — это отдельный процесс административного сервера, он не поднимается автоматически вместе с ragent. Его нужно явно зарегистрировать как службу (Windows) или systemd-unit (Linux) с параметром порта, обычно 1545. Без него утилита rac не сможет обратиться к кластеру удалённо, и весь слой мониторинга сеансов и лицензий не заработает.
Требует ли этот мониторинг доработки конфигурации 1С или установки расширений в базу?
Нет. Всё собирается снаружи: через RAS/RAC на уровне кластера и через системные представления СУБД (DMV в MS SQL, pg_stat_activity/pg_locks в PostgreSQL). Конфигурация 1С и код прикладного решения не затрагиваются вообще.
Почему нет готового официального шаблона Zabbix под RAS/RAC, как есть под MSSQL и PostgreSQL?
В официальном репозитории шаблонов Zabbix действительно нет готового интеграционного шаблона под утилиту rac — это не входит в стандартную интеграцию Zabbix. Поэтому этот слой мы всегда собираем вручную через UserParameter поверх вывода rac, адаптируя парсинг под конкретную версию платформы 1С у клиента.
Как понять, какой порог по времени блокировки СУБД ставить, если у нас нет истории наблюдений?
Мы всегда начинаем с недели наблюдения в режиме Warning-only (без эскалации), чтобы увидеть фактическое распределение длительности блокировок в рабочие и пиковые часы (закрытие периода, начисление зарплаты), и только после этого фиксируем боевые пороги — универсального стартового числа, подходящего всем инсталляциям, не существует.
Учётная запись для мониторинга кластера 1С — это риск для безопасности?
Если завести её с правами администратора кластера только на чтение (без права на завершение сеансов и изменение параметров информационных баз), риск минимален. Мы всегда разводим права: у мониторингового пользователя нет возможности выполнить rac session terminate или изменить sessions-deny — эти операции остаются за инженером вручную по алерту, а не автоматизируются скриптом мониторинга.
📄
Скачайте подробный разбор в PDF Кейсы, статистика, типовые ошибки и чек-лист самопроверки — 12 страниц
Скачать PDF

Подпишитесь на разборы ITfresh

Раз в неделю — практичные материалы по ИТ для бизнеса: без спама, только польза.