При администрировании серверов 1С:Предприятие часто возникает задача автоматизации управления сеансами пользователей. Например, перед выполнением регламентных работ, обновлением конфигурации или резервным копированием базы данных необходимо корректно «выгнать» активных пользователей и завершить зависшие фоновые задания. Для реализации этой логики разработчики часто используют COM-соединение с агентом сервера 1С. Однако на этом пути можно столкнуться с неочевидными методами API и ошибками проектирования. Для автоматического обслуживания баз без ручного отключения пользователей и контроля процессов по расписанию применяется программа для пакетного обновления и резервного копирования 1С.
В этой статье мы подробно разберем, как правильно подключиться к агенту сервера 1С, как получить список активных сеансов, отфильтровать их по типу запущенного приложения (толстый, тонкий, веб-клиент или фоновое задание) и безопасно завершить их работу.
Начинающие разработчики при изучении синтакс-помощника иногда путают понятия «требования назначения функциональности» и «приложения, запущенные пользователями». Метод агента сервера GetAssignmentRules() возвращает массив объектов типа ТребованиеНазначенияСервисов.
Выясним причину ошибки: требования назначения функциональности (функциональность Assignment Rules) используются исключительно в КОРП-лицензиях платформы «1С:Предприятие». Они позволяют гибко распределять нагрузку между рабочими серверами в многосерверном кластере (например, выделять отдельный сервер под фоновые задания или под работу определенных баз данных). Если у вас в кластере всего один рабочий сервер или не используются КОРП-лицензии, этот метод всегда будет возвращать пустой массив. Для получения списка работающих пользователей этот метод абсолютно неприменим.
Для того чтобы узнать, какие приложения и пользователи сейчас работают с информационной базой, нам необходимо использовать метод GetInfoBaseSessions() у объекта соединения с агентом сервера. Этот метод возвращает коллекцию активных сеансов. Для централизованного мониторинга и контроля подключений через COM-соединение можно воспользоваться конфигурацией для внешнего управления сеансами.
Рассмотрим по шагам и разберем весь процесс построения этого механизма в коде 1С:
V83.COMConnector для связи с сервером.ConnectAgent().0).GetInfoBaseSessions().Проанализируем пример кода, реализующий это подключение:
ИмяСервера = "Server1C";
ПортСервера = "1540"; // Стандартный порт агента сервера
ИмяБазы = "Trade_DB";
АдминистраторКластера = "Admin";
ПарольКластера = "P@ssword";
Попытка
Коннектор = Новый COMОбъект("V83.COMConnector");
Агент = Коннектор.ConnectAgent(ИмяСервера + ":" + ПортСервера);
Исключение
ЗаписьЖурналаРегистрации("Администрирование.Подключение",
УровеньЖурналаРегистрации.Ошибка, , ,
"Не удалось создать COM-соединение с агентом сервера: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Кластеры = Агент.GetClusters();
Для Каждого Кластер Из Кластеры Цикл
// Проходим авторизацию администратора кластера
Попытка
Агент.Authenticate(Кластер, АдминистраторКластера, ПарольКластера);
Исключение
Продолжить; // Если авторизация не прошла, пробуем следующий кластер
КонецПопытки;
// Получаем список информационных баз кластера
Базы = Агент.GetInfoBases(Кластер);
ЦелеваяБаза = Неопределено;
Для Каждого База Из Базы Цикл
Если ВРег(База.Name) = ВРег(ИмяБазы) Тогда
ЦелеваяБаза = База;
Прервать;
КонецЕсли;
КонецЦикла;
// Если база найдена в текущем кластере, получаем ее сеансы
Если ЦелеваяБаза <> Неопределено Тогда
Сеансы = Агент.GetInfoBaseSessions(Кластер, ЦелеваяБаза);
Для Каждого Сеанс Из Сеансы Цикл
// Здесь мы можем анализировать свойства каждого сеанса
ИмяПользователя = Сеанс.UserName;
НомерСеанса = Сеанс.SessionID;
ИдентификаторПриложения = Сеанс.AppID;
// Логика фильтрации и отключения
КонецЦикла;
КонецЕсли;
КонецЦикла;
Чтобы реализовать «вариативную реакцию» (например, предупреждать интерактивных пользователей перед отключением, а фоновые задания сбрасывать сразу), необходимо анализировать свойство AppID полученного объекта сеанса. Это свойство возвращает строковый идентификатор клиентского приложения.
Важно: Платформа возвращает строковое значение AppID, которое рекомендуется всегда приводить к нижнему регистру функцией НРег() во избежание ошибок сравнения.
Рассмотрим подробнее полный список основных идентификаторов приложений:
1cv8 — толстый клиент 1С:Предприятия;1cv8c — тонкий клиент 1С:Предприятия;webclient — сеанс пользователя через веб-браузер (веб-клиент);designer — запущенный Конфигуратор;backgroundjob — регламентное или фоновое задание (выполняемое на сервере от имени пользователя или системы);systembackgroundjob — системное фоновое задание (например, обновление полнотекстового поиска, слияние индексов БД);comconnection — внешнее COM-соединение с базой данных;wsconnection — подключение сторонней системы через SOAP Web-сервис;httpconnection или httpserviceconnection — вызов базы данных через HTTP-сервис;odataconnection — обращение к базе данных через автоматический REST-интерфейс OData;srvrconsole — сеанс утилиты администрирования (Консоли кластера).Используя эти идентификаторы, мы можем построить гибкую логику отбора сеансов:
ИдентификаторПриложения = НРег(Сеанс.AppID);
Если ИдентификаторПриложения = "backgroundjob" Или ИдентификаторПриложения = "systembackgroundjob" Тогда
// Это фоновое задание. Его можно завершить без предупреждения.
Агент.TerminateSession(Кластер, Сеанс);
ИначеЕсли ИдентификаторПриложения = "1cv8" Или ИдентификаторПриложения = "1cv8c" Или ИдентификаторПриложения = "webclient" Тогда
// Это интерактивный пользователь. Сначала отправляем предупреждение через ЖР или систему взаимодействия
// И только по истечении таймаута принудительно завершаем сеанс.
КонецЕсли;
Для принудительного разрыва соединения с базой данных используется метод агента сервера TerminateSession(). Ему необходимо передать два параметра: объект кластера и объект конкретного сеанса, полученного из коллекции.
Посмотрим на пример процедуры закрытия всех активных сеансов пользователей, исключая конфигураторы и консоли администрирования:
Процедура ПринудительноЗавершитьСеансыПользователей(Кластер, База, Агент)
Сеансы = Агент.GetInfoBaseSessions(Кластер, База);
Для Каждого Сеанс Из Сеансы Цикл
ИдПриложения = НРег(Сеанс.AppID);
// Не закрываем сеансы администратора кластера и конфигураторы, чтобы не прервать собственную работу
Если ИдПриложения = "designer" Или ИдПриложения = "srvrconsole" Тогда
Продолжить;
КонецЕсли;
Попытка
Агент.TerminateSession(Кластер, Сеанс);
ЗаписьЖурналаРегистрации("Администрирование.ЗавершениеСеансов",
УровеньЖурналаРегистрации.Информация, , ,
СтрШаблон("Успешно завершен сеанс №%1 (Пользователь: %2, Приложение: %3)",
Сеанс.SessionID, Сеанс.UserName, Сеанс.AppID));
Исключение
ЗаписьЖурналаРегистрации("Администрирование.ЗавершениеСеансов",
УровеньЖурналаРегистрации.Предупреждение, , ,
СтрШаблон("Не удалось завершить сеанс №%1: %2", Сеанс.SessionID, ОписаниеОшибки()));
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Важный момент: Бездумное завершение фоновых заданий через метод TerminateSession() несет в себе серьезные инфраструктурные риски. В этот момент транзакция СУБД экстренно обрывается «сверху».
Проанализируем возможные последствия принудительной остановки фоновых заданий:
Рекомендация: Вместо жесткого удаления сеанса фонового задания через сетевой агент COM более безопасно отправлять сигнал отмены через менеджер фоновых заданий платформы 1С. Платформа обработает этот вызов корректно и безопасно откатит транзакции:
// Безопасный способ отмены фонового задания средствами самой конфигурации
Отбор = Новый Структура;
Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно);
АктивныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор);
Для Каждого Задание Из АктивныеЗадания Цикл
// Проверяем имя метода, чтобы случайно не сбросить системные процессы
Если Найти(Задание.ИмяМетода, "Синхронизация") > 0 Тогда
Попытка
Задание.Отменить();
ЗаписьЖурналаРегистрации("Администрирование.ФоновыеЗадания",
УровеньЖурналаРегистрации.Информация, , ,
"Отменено фоновое задание: " + Задание.Наименование);
Исключение
// Задание могло успеть завершиться самостоятельно за время итерации
КонецПопытки;
КонецЕсли;
КонецЦикла;
Использование технологии COM (`V83.COMConnector`) сегодня считается устаревающим и нерекомендуемым подходом по следующим причинам:
Решение: Использование утилиты **RAS** (сервер администрирования кластера) и **RAC** (консольный клиент администрирования). Начиная с современных версий Библиотеки стандартных подсистем (БСП), в конфигурациях доступен общий модуль АдминистрированиеКластера. Он позволяет управлять сеансами, отправляя команды через кроссплатформенный сервер администрирования RAS по протоколу TCP/IP.
Рассмотрим по шагам, как завершить сеансы с помощью инструментов БСП без использования COM-объектов:
// Шаг 1: Задаем параметры подключения к серверу администрирования RAS
ПараметрыКластера = АдминистрированиеКластера.ПараметрыАдминистрированияКластера();
ПараметрыКластера.ТипПодключения = "RAS";
ПараметрыКластера.АдресСервераАдминистрирования = "127.0.0.1";
ПараметрыКластера.ПортСервераАдминистрирования = "1545"; // Стандартный порт RAS
ПараметрыИБ = АдминистрированиеКластера.ПараметрыАдминистрированияИнформационнойБазы();
ПараметрыИБ.Имя = "Trade_DB";
ПараметрыИБ.ИмяАдминистратора = "Admin";
ПараметрыИБ.ПарольАдминистратора = "P@ssword";
// Шаг 2: Получаем активные сеансы через БСП
Фильтр = АдминистрированиеКластера.ФильтрСеансов();
Сеансы = АдминистрированиеКластера.СеансыИнформационнойБазы(ПараметрыКластера, ПараметрыИБ, Фильтр);
СписокСеансовКЗавершению = Новый Массив;
Для Каждого Сеанс Из Сеансы Цикл
// Анализируем свойства сеанса программного интерфейса БСП
Если Сеанс.ИмяПриложения = "1cv8c" Тогда
СписокСеансовКЗавершению.Добавить(Сеанс);
КонецЕсли;
КонецЦикла;
// Шаг 3: Передаем список сеансов на закрытие
Если СписокСеансовКЗавершению.Количество() > 0 Тогда
АдминистрированиеКластера.ЗавершитьСеансы(ПараметрыКластера, ПараметрыИБ, СписокСеансовКЗавершению);
КонецЕсли;
Данный подход является наиболее стабильным, безопасным и кроссплатформенным для современных конфигураций 1С:Предприятие 8.3.
Стоит отметить, что в платформе версии 8.3.24 и выше появился долгожданный встроенный механизм самоочистки «зависших» сеансов.
Ранее, если у пользователя внезапно обрывался интернет (или выключался компьютер), его сеанс продолжал «висеть» на сервере 1С, удерживая клиентскую лицензию и транзакционные блокировки. Чтобы зайти снова при нехватке лицензий, пользователю приходилось обращаться к администратору баз данных для ручного удаления старого сеанса.
Теперь платформа позволяет обычным пользователям (без прав администратора кластера) принудительно завершать **свои собственные** предыдущие сеансы при попытке нового входа. Если при авторизации система обнаруживает блокировку или нехватку лицензий из-за оставшегося активным предыдущего подключения этого же пользователя, платформа выведет интерактивное диалоговое окно с предложением закрыть старые сеансы текущей учетной записи и продолжить работу в новом окне.