Почему динамическое обновление увеличивает потребление памяти на сервере 1С и как с этим бороться?

Системный администратор 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Многие администраторы и разработчики 1С сталкиваются с ситуацией, когда после нескольких динамических обновлений конфигурации (так называемого "демонического обновления") процесс rphost на сервере начинает занимать аномально много оперативной памяти. Нередко объем вырастает на несколько гигабайт за одно обновление. В этой статье мы подробно разберем причины такого поведения, проанализируем механизмы работы менеджера памяти сервера 1С и рассмотрим способы решения этой проблемы.

Механизм динамического обновления и память

Для начала давайте разберемся, почему вообще происходит рост потребления памяти. Когда мы выполняем динамическое обновление, платформа не просто заменяет старый код новым. Процесс происходит сложнее:

  1. Сервер 1С загружает новую версию метаданных в память рабочего процесса rphost.
  2. Старая версия конфигурации остается в памяти. Это необходимо, так как в системе могут находиться активные пользователи, работающие со старой версией объектов.
  3. Пока существует хотя бы один сеанс, использующий старую конфигурацию, сервер вынужден держать в памяти обе версии (или даже несколько версий, если обновлений было много).

Однако, даже когда все пользователи перезашли в программу, мы часто наблюдаем, что память не освобождается. Почему так происходит? Здесь в игру вступает работа менеджера памяти (аллокатора).

Особенности работы менеджера памяти 1С

Сервер приложений 1С (как и многие высоконагруженные системы на C++) использует специфические менеджеры памяти. Главная особенность заключается в том, что процесс rphost захватывает память у операционной системы (ОС), но крайне неохотно возвращает ее обратно.

Мы можем выделить две основные проблемы:

  1. Резервирование: Освобожденная внутри процесса память помечается как "свободная" для повторного использования самим процессом 1С, но с точки зрения Диспетчера задач Windows или Linux она все еще принадлежит процессу.
  2. Фрагментация кучи (Heap Fragmentation): При динамическом обновлении создается множество объектов разного размера. Когда старые объекты удаляются, в памяти образуются "дырки". Если новый объект не помещается в эти "дырки", процесс запрашивает у ОС новые блоки памяти, увеличивая общий объем.

Практический эксперимент: исследование памяти

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

Создадим процедуру заполнения регистра сведений тестовыми данными:


&НаСервере
Процедура FillНаСервере()
    Набор = РегистрыСведений.РегистрСведений1.СоздатьНаборЗаписей();
    Для Сч = 1 По 1000 Цикл
        Запись = Набор.Добавить();
        Запись.Измерение = Новый УникальныйИдентификатор;
        // Создаем длинную уникальную строку для поиска в памяти
        Запись.Ресурс = "TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest";
    КонецЦикла;
    Набор.Записать(Истина);
КонецПроцедуры

&НаКлиенте
Процедура Fill(Команда)
    FillНаСервере();
КонецПроцедуры

Далее создадим процедуру чтения этих данных (чтобы они попали в кэш и оперативную память) и процедуру очистки:


&НаСервере
Процедура QueryНаСервере()
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    РегистрСведений1.Измерение КАК Измерение,
    |    РегистрСведений1.Ресурс КАК Ресурс
    |ИЗ
    |    РегистрСведений.РегистрСведений1 КАК РегистрСведений1";
    Таблица = Запрос.Выполнить().Выгрузить();
КонецПроцедуры

&НаСервере
Процедура ClearНаСервере()
    // Очищаем регистр
    Набор = РегистрыСведений.РегистрСведений1.СоздатьНаборЗаписей();
    Набор.Записать(Истина);
КонецПроцедуры

Суть эксперимента:

  1. Заполняем данные и выполняем запрос. Строки "TestTest..." попадают в память сервера.
  2. Если воспользоваться специализированным сканером памяти (например, ArtMoney или аналогичными инструментами отладки) и поискать строку "TestTest...", мы найдем огромное количество вхождений.
  3. Очищаем регистр сведений процедурой ClearНаСервере.
  4. Логично предположить, что память должна очиститься. Однако повторный поиск покажет, что строки все еще находятся в памяти процесса.
  5. Только при активной записи новых данных (другого содержания и объема) поверх старых, мы увидим, как старые строки постепенно "вымываются".

Этот эксперимент доказывает, что 1С резервирует память и хранит там данные "про запас" или до момента перезаписи, что при частых динамических обновлениях приводит к раздуванию процесса rphost.

Решение проблемы: Настройка перезапуска процессов

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

Способ 1: Автоматический перезапуск по памяти (Рекомендуемый)

В консоли администрирования кластера серверов 1С (или через утилиту rac) необходимо настроить параметры рабочих процессов. Это наиболее "цивилизованный" способ борьбы с утечками.

В свойствах рабочего сервера или кластера найдите настройки:

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

Способ 2: Принудительный ручной перезапуск

Если автоматическая настройка недоступна или нужно освободить память "здесь и сейчас", можно воспользоваться методом изменения интервала перезапуска:

  1. Открываем свойства кластера или рабочего сервера.
  2. Устанавливаем параметр Интервал перезапуска в значение 60 (секунд) или другое малое значение.
  3. Ждем, пока в списке процессов появится новый rphost, а старый перейдет в режим завершения.
  4. Возвращаем настройку Интервал перезапуска в исходное состояние (обычно 0 или 86400).

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

Использование расширений конфигурации

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

Хотя обновление расширений также требует ресурсов и перестроения кэшей, оно считается более безопасным ("мягким"). Сервер накладывает расширение поверх основной структуры. Однако, стоит помнить, что даже при работе с расширениями память rphost может расти из-за необходимости кэшировать объединенную структуру метаданных. Поэтому настройки перезапуска рабочих процессов остаются актуальными и в этом случае.

Резюме

Динамическое обновление действительно "съедает" память из-за дублирования версий метаданных и фрагментации кучи. Полностью избавиться от этого на уровне кода невозможно, так как это особенность работы менеджеров памяти C++ приложений. Эффективным решением является правильная настройка параметров кластера 1С для автоматической рециркуляции (перезапуска) рабочих процессов при превышении лимита памяти.

← На главную