Приложение течёт, а утечки нет: как Next.js съел 4-гигабайтный VPS с 1С
1С падает не всегда из-за 1С. На VPS с 4 ГБ памяти сервер учётной системы можно убить чужим процессом — например, встроенным в Next.js оптимизатором картинок, который без лимита очереди раздувает память до предела. Решение — не чинить код сайта, а вынести 1С на сервер, где её ресурсы не делят ни с кем.
9:47 утра: накладные не открываются
Компания продаёт крепёж и стройматериалы оптом, 23 постоянных пользователя в 1С:Управлении торговлей, склад и офис в Москве. В 9:47 бухгалтер пишет в чат ИТ-подрядчика: накладные не открываются, программа зависла на «Загрузка данных». Через минуту то же самое пишет менеджер по продажам — не формируется счёт клиенту, который ждёт на линии. Через пять минут жалуется склад: терминал сборки заказов вообще не подключается к базе.
Первая версия дежурного администратора — упала база. Он открывает консоль кластера и видит: процесс rphost не завис, а именно исчез, будто его выключили извне. Перезапуск помогает на две минуты — потом всё повторяется. Только в системном логе сервера находится короткая строка: «Out of memory: Killed process rphost». Процесс не подвис — его убил сам Linux, и убивал по кругу, пока не разобрались, откуда берётся давление на память.
что стояло на сервере до сбоя
Год назад компания решила сэкономить и завела сайт-каталог с фотографиями товара — витрину для партнёров на Next.js, чтобы менеджеры по закупкам могли смотреть остатки и фото без звонка в офис. Отдельный сервер под него не стали разворачивать: арендованный VPS на 4 ГБ памяти и так простаивал ночью и по выходным, вот и посадили сайт туда же, рядом с кластером 1С. Нагрузка на сайт казалась несерьёзной — пара десятков посетителей в день, экономия выглядела разумной.
Полгода всё работало ровно: сайт открывался быстро, база не тормозила, счёт за сервер не рос. Никто не считал, сколько памяти реально забирает каждый процесс в пике, — обе системы работали в границах, которые никто не проверял на пределе.
На сервере крутились кластер 1С (ragent, rmngr и несколько rphost под конкретные информационные базы), PostgreSQL и рядом — процесс Node.js со встроенным в Next.js оптимизатором картинок, который на лету сжимает и меняет размер загруженных фото под разные экраны и устройства.
как оптимизатор картинок съедает память, которую потом не отдаёт
В то утро менеджер по контенту запустил переиндексацию каталога — обновил фотографии сразу для 240 позиций после смены поставщика упаковки. Сайт не хранит уменьшенные копии заранее: он генерирует их по первому запросу через встроенный эндпоинт /_next/image, а результат кладёт в кеш только после того, как отдаст картинку. Краулер поисковика и предпросмотр в админке дёрнули почти весь каталог одновременно, до того как кеш успел прогреться, — на сервер за минуту прилетело около двухсот параллельных запросов на изменение размера картинок.
Каждый такой запрос — отдельный процесс sharp, который разворачивает изображение в памяти целиком, меняет размер и только потом отдаёт результат и освобождает память. Один процесс — 150-300 МБ, в зависимости от исходника и формата. Двести параллельных процессов при отсутствии лимита очереди — это уже не утечка в привычном смысле: память не «протекает» тихо неделями, её съедают за минуты и она честно возвращается назад, как только процесс закончит работу. Но очередь не успела разобраться, а свободные 4 ГБ кончились раньше, чем первые процессы успели отработать.
Перед тем как сервер убил rphost, он несколько секунд боролся: включился своп, диск начал захлёбываться, отклик всех сервисов на сервере просел одновременно. Поэтому пользователи 1С почувствовали не мгновенный обрыв, а сначала подвисание — то самое «Загрузка данных», которое бухгалтер приняла за баг базы.
Дальше в дело вступил oom-killer — механизм ядра Linux, который при нехватке памяти выбирает и завершает процесс с самым высоким «баллом обжорства». Он не разбирает, кто виноват: смотрит на текущее потребление и время жизни процесса. У кластера 1С к тому моменту было около сотни активных сессий, и по сумме занятой памяти rphost набрал больше очков, чем разрозненные короткоживущие процессы sharp. Убили не виновника, а соседа, который просто оказался тяжелее в моменте проверки.
это не только Next.js
Оптимизатор картинок — частный случай общей ловушки. Точно так же ведёт себя любой процесс без лимита памяти и очереди: массовая рассылка с генерацией PDF-счетов, импорт прайса от поставщика, экспорт отчёта в Excel на тысячи строк, резервное архивирование не в своё окно. У всех один и тот же почерк: разовый всплеск, который система не ограничивает заранее, и сосед по серверу, у которого в этот момент не оказалось запаса. Чем больше на сервере разнородных сервисов, тем выше шанс, что рано или поздно всплеск устроит не тот процесс, который все подозревают в первую очередь.
цена сорока минут простоя
Инцидент можно было списать на разовую случайность и забыть. Но день пришёлся на закрытие месяца: бухгалтерия проводила регламентные документы, склад отгружал по счетам, которые нельзя перенести на завтра. Сорок минут, пока администратор поднимал кластер 1С вручную и разбирался в причине, — это конкретные счета, которые клиенты ждали к обеду, отгрузки, которые встали в очередь на завтра, и отчёт, который бухгалтерия должна была закрыть до конца дня, а не когда сервер снова согласится работать.
Дальше дороже. Если сайт не ограничить, всплеск нагрузки на оптимизатор картинок повторится при следующей массовой загрузке фото — например, перед сезонным прайсом, когда обновляют сразу тысячи позиций. И каждый раз это будет выглядеть как «опять упала база», хотя база тут ни при чём, а доверие к учётной системе у сотрудников падает быстрее, чем восстанавливается.
три способа не наступить на те же грабли
У проблемы есть три уровня решения — от временной заплатки до полного разделения ресурсов, и выбор зависит от того, сколько людей реально зависят от 1С каждый день.
| Вариант | Что решает | Ограничение | Когда достаточно |
|---|---|---|---|
| Лимит очереди у оптимизатора картинок (nginx или настройка Next.js) | Убирает конкретный триггер инцидента | Не защищает от следующего «прожорливого» процесса на том же сервере | Разовый инцидент, есть ресурс разработчика |
| Виртуальный сервер для 1С отдельно от сайта | 1С получает собственные CPU и память, сайт больше не сосед | Нужно настроить перенос базы и терминальный доступ | Малый и средний бизнес, до 20-30 пользователей 1С |
| Выделенный сервер под 1С | Полная изоляция от чужих нагрузок, максимум производительности для крупной базы | Дороже виртуального, избыточно для небольшой базы | Растущая база, сервер под 1С:ERP, десятки сессий |
| Ничего не менять, полагаться на запас памяти | Не требует затрат прямо сейчас | Инцидент повторится при следующем всплеске у соседнего процесса | Формально достаточно, пока не рвануло второй раз |
что сделали за оставшийся день
Подрядчик выбрал второй вариант: за оставшийся день кластер 1С перенесли на отдельный виртуальный сервер для 1С с гарантированными 8 ГБ памяти под саму учётную систему, а сайт с оптимизатором картинок остался на старом VPS — там же ограничили очередь запросов к /_next/image через nginx, чтобы больше двадцати параллельных resize-задач не запускалось одновременно, и добавили лимит памяти на сам процесс Node.js через cgroups, чтобы при следующем всплеске упал только сайт, а не всё вокруг.
Заодно пересмотрели настройку сервера 1С: резервное копирование вынесли на ночное окно, добавили мониторинг свободной памяти с порогом в 20% и алертом администратору, чтобы он увидел проблему раньше, чем её увидит бухгалтерия. Перенос проверили нагрузочным тестом — сымитировали пиковый день закрытия месяца, прежде чем отпустить пользователей работать в новой схеме. С того дня инцидент не повторялся: даже когда сайт снова ловил всплеск от переиндексации каталога, кластер 1С об этом не узнавал — у него был собственный сервер и собственная память, которую больше никто не мог занять.
Перенос обошёлся дешевле, чем казалось на старте: аренда сервера для 1С начинается от 3300 руб/мес, а сама аренда 1С — от 1100 руб/мес, если лицензии тоже переносить в облако. Для компании с 23 пользователями это оказалось дешевле, чем один час простоя отдела продаж в месяц закрытия периода.
как проверить свой сервер, пока он не повторил этот сценарий
- ✓Посмотреть системный лог на записи oom-killer — команда dmesg покажет, убивал ли Linux процессы за последнюю неделю, и по каким именно процессам.
- ✓Сравнить реальное потребление памяти кластером 1С под пиковой нагрузкой с официальными системными требованиями 1С — часто запас считали три года назад, а база и число пользователей выросли втрое.
- ✓Выяснить, какие ещё процессы живут на том же сервере, что и 1С, и есть ли у них лимиты по памяти и числу параллельных задач, а не только у самой 1С.
- ✓Если сервер обслуживает и сайт, и учётную систему, оценить, что для бизнеса дороже — час простоя 1С или час простоя сайта, и развести их по разным серверам в первую очередь, не дожидаясь второго инцидента.
Разбор такого инцидента и перенос базы на отдельный сервер у наших администраторов занимает от нескольких часов до дня — в зависимости от размера базы и числа информационных баз в кластере. Отдельные работы по настройке и сопровождению считаются по факту: сисадмин и сопровождение 1С — от 3800 руб/час.
❓ Частые вопросы
Почему при поломке сайта на сервере падает и 1С — это же разные программы?
Потому что на одном сервере программы делят общую память и процессор. Если у сайта случается всплеск нагрузки без лимита — например, оптимизатор картинок запускает сразу сотни процессов — свободная память заканчивается, и Linux начинает завершать процессы по своим правилам. Под удар попадает не виновник, а тот, кто в моменте занимает больше памяти, и это часто оказывается кластер 1С.
Как понять, что 1С упал именно из-за нехватки памяти, а не из-за самой базы?
Проверьте системный лог сервера командой dmesg или /var/log/syslog на записи вида «Out of memory: Killed process». Если там есть имя процесса 1С — rphost или ragent, — систему убило нехваткой памяти, а не ошибкой в базе или конфигурации.
Сколько памяти реально нужно серверу для 1С?
Зависит от числа пользователей, размера базы и конфигурации — точные ориентиры есть в официальных системных требованиях 1С. На практике для 15-25 активных пользователей комфортный запас начинается от 8 ГБ, отдельно от других приложений на том же сервере.
Можно ли держать 1С и сайт компании на одном сервере вообще?
Для совсем небольшой нагрузки можно, но с жёсткими лимитами памяти для каждого процесса. Как только один из сервисов начинает расти или получать всплески — импорт, рассылка, пересчёт картинок, — риск конфликта за ресурсы растёт быстрее, чем кажется, и разделение серверов окупается почти сразу.
Сколько стоит перенести 1С на отдельный сервер?
Аренда виртуального сервера для 1С начинается от 3300 руб/мес, аренда самой 1С в облаке — от 1100 руб/мес. Итоговая цена зависит от числа пользователей и конфигурации базы; работы по переносу и настройке считаются отдельно, сисадмин и сопровождение — от 3800 руб/час.
Или позвоните: +7 495 133-92-44 — в рабочее время с 9:00 до 19:00
Остались вопросы? Нужна помощь?
Менеджеры компании с радостью ответят на ваши вопросы, произведут расчет стоимости услуг и подготовят индивидуальное коммерческое предложение.
Бесплатная консультация

