Оригинал статьи опубликован на habrahabr.ru
Взял VPS, построенный на OpenVZ. Поставил туда Debian Lenny и всякие программы (обычный LAMP, по сути). С точки зрения потребления ресурсов ничего почти не настраивал, вышло где-то 200М занятой оперативной памяти (сразу после старта).
Написал
|
|
в /etc/init.d/rc ближе к верху. Перезагрузился. Потребление памяти на VPS упало более чем вдвое, стало около 100М.
Если у Вас VPS на Xen или аналогичных, то у Вас нет граблей, с которыми я тут боролся. Если на OpenVZ (Virtuozzo) со товарищи — у Вас, скорее всего, на VPS эти же грабли.
В статье — почему и как это работает.
OpenVZ vs Xen
Отличие OpenVZ от Xen, которое нас тут интересует: в OpenVZ ограничивается виртуальная память. Т.е., например, тарифы вида «256М + 256М burstable» означают, что нам доступно макс. 256М именно виртуальной памяти (и 512М виртуальной по праздникам).
Многие программы выделяют себе виртуальной памяти «про запас», т.к. при обычной работе (или виртуализации через Xen со товарищи) ее можно выделить сколько угодно (втч > доступной физически) безо всяких последствий. Это одна из причин, по котрой VPS на Xen стоят дороже аналогичных по характеристикам VPS на OpenVZ — они реально предоставляют больше ресурсов.
Но это еще не все
На каждый запущенный тред в виртуальной памяти выделяется место под стек. Так вот, в debian lenny, например, по умолчанию это место = 10М. Берем какой-нибудь apache с mpm_worker (который создает кучу тредов), запускаем под OpenVZ — тратятся сотни мегабайт памяти.
10 мегабайт под стек — это много. А установлено столько, т.к. при нормальном запуске linux эта память «бесплатная» — можно было бы хоть 100M установить без негативных эффектов (разве что программы с багами на рекурсию агонизировали бы дольше). Обычно программам требуется в разы меньше, даже с учетом «про запас».
Уменьшаем размер стека по умолчанию
Сервер — не компьютер общего пользования, заранее известны программы, которые там будут запускаться. Программы эти делают обычно одно и то же постоянно. Причин резких изменений размера необходимой им под стек памяти как-то не вижу.
Уменьшить размер стека по умолчанию можно командой
|
|
. Параметр меняется для программ, запущенных из текущего шелла (ну иерархически тоже ессно). Запускаем эту штуку при загрузке системы (внутри скрипта, стартующего демоны) — и все.
Тут очевидное предупреждение — если установить слишком низкий лимит, что-нибудь сложное (с кучей рекурсивного кода или непонятно-зачем-хитрой работой со стеком) может начать падать. Осторожность не повредит. Вы предупреждены. Делайте бэкапы. Но 10M под стек — это, в большинстве случаев, очень много)
Мне показался оптимальным размер 2М. Экстремалы и экспериментаторы могут снижать и дальше (пробовал, у меня и на 32К все работало прекрасно), но там выигрыш уже небольшой получается, а риск возрастает, смысла мало вообщем. Хотя — пробуйте.
В принципе, запуск ulimit для всех процессов — довольно грубо. Для более тонкой настройки можно(задолбаться) править скрипты запуска отдельных демонов. Также у некоторых программ можно в конфигах менять память, которую они будут выделять на стек треда, пример — apache, директива ThreadStackSize для mpm_worker. Собственно говоря, у меня апач и был настроен в режиме worker (php — через fastcgi, если что), а память на стек ограничивалась с помощью ThreadStackSize без ulimit (то снижение в 2 раза было за счет mysql с InnoDB, fastcgi-процессов php, mail-сервера и всякой мелочи).
Для тестирования всего этого дела, если боязно лезть сразу в /etc/init.d/rc, можете
- посмотреть, сколько занимает в памяти какой-нибудь процесс,
- в шелле ввести ulimit -s <сколько-нибудь, в килобайтах>,
- перезапустить процесс (что-нибудь в духе /etc/init.d/mysql restart)
- посмотреть еще раз, сколько теперь занимает, и проверить, что все работает
Мысли
В итоге мы имеем: пользователи OpenVZ расплачиваются кучей оперативной памяти за возможность когда-нибудь (черти когда) запустить редкую хитрую программу, тогда как всем остальным это не стоит ничего. Поэтому поступаем, как мне кажется, логично: при виртуализации OpenVZ снижаем макс. глубину стека до 1-2М. На всяких HP-UX (который я, правда, в глаза не видел), например, 64К, и не плачут. А от снижения макс. глубины стека освобождается куча оперативной памяти для более важных штук.
Критика и замечания:
- Апач с 15k витхостов требует ulimit -s unlimited
Хотя 15k на vps не будут пускать, тем не менее — учтите, что чем больше энтропия, тем выше требования к стеку - Кроме снижения потребления оперативной памяти в OpenVZ (РБК Хостинг), есть еще параметры user beancounters, которых тоже может нехватать. Я решил все эти проблемы следующим образом: Убил Apache, поставил Nginx, уменьшил в nginx sndbuf до 16k, так как именно его мне нехватало при увеличении количества соединений до 1000. В настоящий момент система спокойно поддерживает до 1000 соединий (лимит по tcp сокетам хостинга)
- Лимиты для пользователя или группы штатно можно задавать в /etc/security/limits.conf.
- Только что прописал ulimit -s 1024 в /etc/init.d/rc До этого VPS висел, жутко не хватало памяти. Сейчас вроде нагрузка упала. Было 250-270 Мб, стало 140-150. Немного растет постепенно, но не смертельно. Спасибо!