Məzmuna keç
Tez Base

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

· Dərc edilib: · Yenilənib:

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

За одиннадцать суток рабочий процесс сервера приложений распух с 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С. Если рост памяти привязан к определённой операции, сбор технологического журнала поможет уточнить участок выполнения.

Bunu sizin əvəzinizə həll edə bilərəm

Reqlament xidmətini elə qururuq ki, baza stabil işləsin, ehtiyat nüsxələr zəmanətlə bərpa olunsun, disklərdəki yer isə qəfil bitməsin.

Qiyməti
450 000 ₸-dənbirdəfəlik sazlama; müşayiət - ayda 150 000 ₸-dən; vergilərsiz

Yazmaq tezdir? Özünüz ölçün

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

Emalı aç

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

Bunu da oxuyun

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

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

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

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

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

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