Перейти к содержимому
Tez Base

Рабочий процесс 1С растёт по памяти: как это замерить и что выставить

· Опубликовано: · Обновлено:

Мониторинг и журналы

За одиннадцать суток рабочий процесс сервера приложений распух с 7,22 гигабайта до 12,72: ровно по полгигабайта в день, прямой линией, без ступеней и плато. Сбросить рост может только перезапуск сервиса, ведь ни одного лимита памяти в кластере не задано.

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

Сразу честно: рост на полгигабайта в сутки - симптом. Что именно держит память, мы не выяснили. Лимиты с вежливым перезапуском утечку не лечат, только не дают ей уронить сервер. Замеренного “после” тоже нет, всё ниже - настройки на момент разбора.

Числа взяты с одной машины на четыре ядра и 32 гигабайта. Там крутятся сразу сервер терминалов, 1С 8.3.27 как сервер приложений, толстые и тонкие клиенты вместе с браузерами пользователей, плюс локальный PostgreSQL 18. Совмещать так спорно, зато вывод из этого полезный: процессор на такой машине физически не упрётся в потолок раньше памяти, потому что каждый сеанс обходится в гигабайты и десятки мегагерц. Метрики снимались раз в пятнадцать секунд на протяжении двух недель.

Шаг 1: убедиться, что метрика не врёт

Три проверки, каждая снимает свой класс ложных выводов. Делать их надо до того, как пойдёте что-то настраивать, иначе настроите не то.

Порядок чтения: среднее, доля времени, максимум

Сводная таблица суточных максимумов рисовала дисковую подсистему загруженной на 97-99 % ежедневно, все дни подряд. Вывод сам просится: диск в потолке, пора расширять. И вывод удобный: одним махом объясняет всё и сводится к бюджету.

А среднее по тому же ряду - 4,24 %. Расхождение в двадцать три раза уже диагноз: ресурс свободен, у него лишь бывает короткий пик, он-то и попадает в максимум.

Третья цифра - доля времени над порогом. Выше 80 % диск за неделю поднимался в 7 пятиминутках из 2016, то есть треть процента времени. Откуда 2016: столько пятиминуток в неделе. Семь всплесков за семь суток, по одному каждую ночь, и это окно резервного копирования, по журналу минут шесть.

Хуже суточного максимума метрики для суждения о перегрузке не найти. Из него видно лишь, что ресурс когда-то был занят, а как долго, он не говорит. Читать надо в таком порядке: среднее (есть ли нагрузка вообще), доля времени выше порога (мешает ли она), максимум (уточнение к первым двум).

Долю времени считать несложно, если ряд лежит в CSV:

# Доля времени, когда счётчик был выше порога. Порог и путь подставьте свои.
$porog = 80
$ryad  = Import-Csv 'C:\metrics\disk.csv'
$vsego = $ryad.Count
$vyshe = ($ryad | Where-Object { [double]$_.Value -gt $porog }).Count
'{0} из {1} замеров выше {2}% = {3:N2}% времени' -f $vyshe, $vsego, $porog, (100 * $vyshe / $vsego)

Меньше процента - расширять ресурс незачем: у вас не перегрузка, а регламентная операция, и её надо либо принять, либо развести по времени.

Разрешение ряда: прореженный врёт в обе стороны

Ради скорости отрисовки графиков ряд проредили до шага в пять минут: на интервал оставалось одно значение. И свободное место на диске по такому ряду выглядело благополучно.

Сырые данные с шагом пятнадцать секунд показывают другое: почти ежедневно свободное место проседает до 27-450 мегабайт. Ориентироваться в таком разбросе стоит на нижнее значение, а при 27 мегабайтах база писать уже не может.

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

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

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

Какую цифру памяти вообще смотреть

Их две, и их постоянно путают.

  • Резидент (Working Set) - то, что процесс физически держит в оперативной памяти. Это показывает диспетчер задач.
  • Коммит (Private Bytes) - то, что процесс попросил у системы и получил, независимо от того, вытеснено оно в подкачку или нет.

Разница бывает кратной: в нашем разборе аварийных дампов попался процесс с резидентом 379 МБ и коммитом 1371 МБ, в 3,6 раза больше. Мониторинг, следящий за резидентом, роста просто не увидит, а отказы “не удалось выделить память” считаются по коммиту. Снимать надо Private Bytes.

Шаг 2: собрать ряд и посчитать наклон

Отдельный инструмент не нужен, достаточно писать в CSV раз в минуту и хранить месяц:

# Сбор памяти рабочих процессов 1С в CSV. Ставится в планировщик
# на запуск при старте системы, с перезапуском при сбое.
$fajl = 'C:\metrics\rphost.csv'
if (-not (Test-Path $fajl)) {
    'Vremya;Process;PID;PrivateMB;WorkingMB' | Out-File $fajl -Encoding utf8
}

while ($true) {
    $moment = (Get-Date).ToString('yyyy-MM-dd HH:mm:ss')
    foreach ($p in Get-Process -Name rphost, rmngr, ragent -ErrorAction SilentlyContinue) {
        $priv = [math]::Round($p.PrivateMemorySize64 / 1MB, 1)
        $work = [math]::Round($p.WorkingSet64        / 1MB, 1)
        "$moment;$($p.ProcessName);$($p.Id);$priv;$work" | Add-Content $fajl -Encoding utf8
    }
    Start-Sleep -Seconds 60
}

Тот же ряд снимается счётчиками производительности, если сборщик уже есть: \Process(rphost*)\Private Bytes и \Process(rphost*)\Working Set.

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

# Наклон роста внутри одного отрезка между перезапусками.
# PID у нового процесса другой, поэтому группируем по нему - это и есть отрезок.
Import-Csv 'C:\metrics\rphost.csv' -Delimiter ';' |
    Where-Object { $_.Process -eq 'rphost' } |
    Group-Object PID |
    ForEach-Object {
        $tochki = $_.Group | Sort-Object { [datetime]$_.Vremya }
        $ot     = $tochki[0]
        $do     = $tochki[-1]
        $chasov = ([datetime]$do.Vremya - [datetime]$ot.Vremya).TotalHours
        if ($chasov -gt 6) {
            $rost = ([double]$do.PrivateMB - [double]$ot.PrivateMB) / 1024
            [pscustomobject]@{
                PID        = $_.Name
                Chasov     = [math]::Round($chasov, 1)
                StartGB    = [math]::Round([double]$ot.PrivateMB / 1024, 2)
                KonecGB    = [math]::Round([double]$do.PrivateMB / 1024, 2)
                GBvSutki   = [math]::Round($rost / $chasov * 24, 2)
            }
        }
    } | Format-Table -AutoSize

Как читать результат:

  • за неделю подросла и к исходному уровню ни разу не вернулась - та самая история;
  • ступеньки вниз - память отдаётся обратно, процесс нормально работает под нагрузкой;
  • пила на графике за месяц - смотрите внутрь отрезка. С перезапуском сервиса ряд стартует заново, и при перезагрузках раз в неделю рост выглядит безобидно, а по всему окну наклон смазывается до нуля. Поэтому в скрипте группировка по PID: новый процесс - новый отрезок.

Шаг 3: заполнить четыре свойства кластера

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

СвойствоКогда срабатываетКак выбирать
Объём памяти рабочих процессов, до превышения которого сервер считается производительныммягкий порог, с него начинается вежливый перезапусксчитается от объёма машины: суммарный потолок процессов должен оставлять запас системе, СУБД и клиентам. При 32 ГБ и одном процессе - заметно ниже двенадцати
Интервал превышения допустимого объёма памятисколько секунд превышение терпитсяот темпа роста. При полугигабайте в сутки счёт идёт на часы, минутные интервалы ни к чему
Максимальный объём памяти рабочих процессовжёсткий потолок, аварийный стопв норме срабатывать не должен, поэтому вплотную к мягкому порогу не ставится: нужен зазор, в котором мягкий механизм успеет отработать
Безопасный расход памяти за один вызовлимит на один серверный вызовловит запрос, решивший поднять в память полбазы. До постепенного роста ему дела нет, но без него один неудачный отчёт кладёт процесс вместе со всеми, кто в нём сидел

Интервал задаётся в секундах, объёмы в байтах. Ноль везде означает “без ограничения”, и читается он обычно как “ограничений не нужно” - ровно та ошибка, из-за которой механизм у большинства выключен.

Прочитать и поменять из командной строки

Через консоль это делается мышью, но если серверов несколько или нужна воспроизводимость, есть rac - консольный клиент администрирования (лежит рядом с платформой, работает через службу ras).

# 1. Узнать идентификатор кластера
rac cluster list

# 2. Список рабочих серверов кластера
rac server list --cluster=<uuid-кластера>

# 3. Все свойства сервера с текущими значениями
rac server info --cluster=<uuid-кластера> --server=<uuid-сервера>

Третья команда главная: она печатает точные имена ключей вместе с текущими значениями, и эти же имена принимает rac server update в виде --ключ=значение.

⚠️ Имена ключей берите из вывода info, а не по памяти и не из статей: между версиями платформы они менялись, и команда с устаревшим ключом либо не отработает, либо выставит не то свойство. Проверять результат надо повторным info, а не по факту отсутствия ошибки.

Если службы ras нет, rac не с чем соединяться. Ищите её внимательно: у Windows есть системные службы с теми же именами, к 1С они не относятся, но в списке выглядят как нужные. Смотрите на путь к исполняемому файлу, а не на имя.

Сколько держать рабочих процессов

Если процесс на установку один, его перезапуск задевает всех разом. С двумя и более кластер может переселять соединения без заметной паузы. Настройки вида “сделать три” не существует: новый процесс появляется сам, как только кластер упрётся в “Количество соединений на процесс” либо в “Количество информационных баз на процесс”. А каждый процесс сам по себе ест память, и плавные перезапуски мы оплачиваем гигабайтами, что на машине с 32 ГБ ощутимо.

Шаг 4: проверить таймауты терминальных сеансов

Эта находка дешевле и обиднее предыдущей. Сеансы, отключённые на терминальном сервере, не завершались вообще: в политике все три таймаута стоят в нуле, а ноль тут значит “без ограничения”. В результате шесть мёртвых сеансов круглые сутки занимали 9-11,6 гигабайта. Толстый клиент плюс открытый браузер - это по полтора-два гигабайта на каждый сеанс, цена нормальная. Ненормально то, что сеансы живут вечно.

Треть памяти машины возвращается одной настройкой, прикладной код при этом никто не трогает.

Групповая политика: Конфигурация компьютера → Административные шаблоны → Компоненты Windows → Службы удалённых рабочих столов → Узел сеансов удалённых рабочих столов → Ограничения по времени для сеансов. Четыре параметра, и настраивать их надо вместе:

ПараметрПро чтоСтоит трогать
Ограничение по времени для отключённых сеансовпользователь закрыл окно крестиком и ушёлда, это чистая память, лежащая мёртвой
Ограничение для активных, но бездействующих сеансовсессия открыта, в ней ничего не происходитда
Ограничение по времени для активных сеансовсамый агрессивный, выкинет работающегоосторожно, обычно не нужен
Завершать сеанс при достижении ограничениязавершать или только отключатьобязательно, иначе “отключать” вернёт сеанс в первую категорию

Последний пункт и есть ловушка: без него первые два не освобождают память, а переводят сеанс в состояние “отключён”, где он продолжает её держать.

Что реально выставлено, читается из реестра одной командой:

# Действующие ограничения сеансов RDS. Значения в миллисекундах,
# 0 или отсутствие значения означает "без ограничения".
$put = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services'
'MaxDisconnectionTime','MaxIdleTime','MaxConnectionTime','fResetBroken' | ForEach-Object {
    $v = (Get-ItemProperty -Path $put -Name $_ -ErrorAction SilentlyContinue).$_
    [pscustomobject]@{
        Parametr = $_
        Znachenie = if ($null -eq $v) { 'не задано' }
                    elseif ($_ -eq 'fResetBroken') { if ($v -eq 1) { 'завершать' } else { 'только отключать' } }
                    elseif ($v -eq 0) { 'без ограничения' }
                    else { '{0} мин' -f ($v / 60000) }
    }
} | Format-Table -AutoSize

А это - кто висит прямо сейчас и сколько такой сеанс стоит:

# Отключённые сеансы и память, которую они держат.
# query session даёт состояние, Get-Process - вес по сеансам.
query session | Select-String 'Disc' | ForEach-Object { $_.Line }

Get-Process -ErrorAction SilentlyContinue |
    Where-Object { $_.SessionId -ne 0 } |
    Group-Object SessionId |
    ForEach-Object {
        [pscustomobject]@{
            Sessiya   = $_.Name
            Processov = $_.Count
            PrivateGB = [math]::Round((($_.Group | Measure-Object PrivateMemorySize64 -Sum).Sum) / 1GB, 2)
        }
    } | Sort-Object PrivateGB -Descending | Format-Table -AutoSize

Сопоставьте два вывода: сеансы в состоянии Disc с весом в полтора-два гигабайта и есть мёртвые. Завершается такой сеанс командой logoff <идентификатор>, но правильное лечение - политика, иначе они наберутся снова к концу недели.

Ошибка, которую легко повторить: арифметика объяснения

Этот раздел про метод, и он стоит отдельно, потому что ловушка тут не техническая.

Посреди наблюдения производительность в один из дней провалилась. Объяснение лежало на поверхности: 12,7 гигабайта у рабочего процесса, десять у мёртвых сеансов, в сумме 22,7 из 32, свободной памяти почти ноль, вот и провал.

Объяснение красивое, только арифметика в нём не сходится. До пика в 12,72 гигабайта процесс дорос к одиннадцатым суткам, а провал был на пятые. К тому дню у него было 7,22 плюс полгигабайта за каждый из четырёх дней, то есть примерно 9,2 гигабайта. С сеансами выходит 19,2 против 22,7, разница три с половиной гигабайта. По такому счёту свободных должно было остаться около 12,8 гигабайта, фактически же доступно было 3,15. Выходит, в день провала ещё около девяти с половиной гигабайт забрал кто-то третий: браузеры, клиенты или локальная СУБД. Этот вопрос в разборе остался открытым.

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

Что памяти и правда не хватало, подтверждается косвенно: при 32 физических гигабайтах выделено было 33,49. С таким превышением без подкачки не обойтись, и отчёт её фиксирует. Только лечить нужно не подкачку.

Что проверить заранее, чтобы разбор не встал

На каждую из трёх вещей ушло время.

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

# Перезапускать службу при сбое: первые два раза через минуту, дальше тоже.
sc.exe failure '<ИмяСлужбы>' reset= 86400 actions= restart/60000/restart/60000/restart/60000
sc.exe config  '<ИмяСлужбы>' start= delayed-auto

Не зарегистрирована служба администрирования кластера: rac молчит, и настройки остаётся вытаскивать из файла кластера вручную.

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

Границы

Откуда рост памяти, не установлено. Темп и линейность известны, а что именно не освобождается, неясно. Лимиты лишь страхуют.

Замера “после” нет ни для одной из двух находок. На момент разбора таймауты и лимиты только предложены, и обещать результат в гигабайтах я не берусь.

Долю времени выше порога считали за неделю, хотя наблюдали две. По всему окну она вдвое ниже, и вывод “диск свободен” от этого только твёрже. Само число на другое окно не переносите.

Чек-лист

  1. Посчитать среднее и долю времени выше порога, максимум оставить на потом.
  2. Проверить разрешение ряда: для минимумов брать сырой, не прореженный.
  3. Снимать Private Bytes, а не Working Set.
  4. Считать наклон внутри отрезка между перезапусками, группируя по PID.
  5. Заполнить четыре свойства кластера: по умолчанию там ноль, то есть без ограничений.
  6. Проверить три таймаута RDS и обязательно параметр “завершать сеанс”.
  7. Проверить арифметику собственного объяснения, особенно если оно всем понравилось.

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

Соседние разборы и инструменты

Если процесс не растёт, а падает, лечение совсем другое: там нужны дампы, настройка их сбора и обращение в поддержку. Это отдельная история - разбор аварийных дампов 1С без WinDbg, на данных 354 дампов. Если память ровная, а rphost или rmngr держит процессор, порядок поиска другой: сервер 1С грузит процессор.

Чек-ап СУБД под 1С - если СУБД стоит на той же совмещённой машине, что и сервер приложений, и делит с ним память. Больше сорока проверок с вердиктом, что не так в настройке.

Карта объёмов базы 1С - когда вслед за памятью подходит к концу и диск, первым делом разберитесь, из чего состоит сама база.

Анализ нагрузки кластера 1С - когда память съел конкретный сеанс, а не процесс вообще: обработка по снимкам сервера администрирования показывает, какой сеанс сколько потребил и кто держал блокировки.

Проверка после изменения настроек

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

Могу починить это за вас

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

Стоимость
450 000 - 600 000 ₸ТЗ и разовая наладка, без налогов; сопровождение - от 150 000 ₸/мес отдельно

Рано писать? Измерьте сами

Самый нагруженный процесс не всегда виноват

Открыть обработку

INFOSTART TECH EVENT 2026: конференция для 1с-специалистов. если собираетесь, регистрируйтесь по нашей ссылке. Регистрация →

Читайте также

Бэкап базы 1С есть, а файлов из томов в нём нет: как проверить заранее

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

Нарушение прав доступа в 1С: как узнать, какого права не хватило, и какую группу доступа выдать

Пользователь видит одну строку "Нарушение прав доступа!", а объект и имя права уже лежат в журнале регистрации. Разбор по шагам: как прочитать событие, как по праву найти роли, профили и самую узкую группу доступа, почему после выдачи права приходит новый отказ и в каких случаях выдавать права бесполезно.

Перенос базы 1С с PostgreSQL 18 на 17: восстановление по сети клиентом старшей версии

pg_restore версии 17 архив версии 18 не читает, а обновлять приёмник нельзя или некогда. Рабочий путь: запустить pg_restore 18 на источнике и направить его по сети в сервер 17. Методика целиком: какие пути тупиковые и почему, настройка доступа на приёмнике, выгрузка и загрузка в четыре потока, SQL-сверка таблиц и индексов, почему база после переноса меньше и как считать окно работ по одной таблице. С замерами на двух базах 1С.