Пользователь
0,0
рейтинг
2 марта 2009 в 02:09

Администрирование → Как можно снизить потребление оперативной памяти на VPS в 2 раза, ничего не меняя в настройках программ

Взял VPS, построенный на OpenVZ. Поставил туда Debian Lenny и всякие программы (обычный LAMP, по сути). С точки зрения потребления ресурсов ничего почти не настраивал, вышло где-то 200М занятой оперативной памяти (сразу после старта).
Написал ulimit -s 1024 в /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 установить без негативных эффектов (разве что программы с багами на рекурсию агонизировали бы дольше). Обычно программам требуется в разы меньше, даже с учетом «про запас».

Уменьшаем размер стека по умолчанию


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

Уменьшить размер стека по умолчанию можно командой ulimit -s <размер стека на тред в Кб>. Параметр меняется для программ, запущенных из текущего шелла (ну иерархически тоже ессно). Запускаем эту штуку при загрузке системы (внутри скрипта, стартующего демоны) — и все.

Тут очевидное предупреждение — если установить слишком низкий лимит, что-нибудь сложное (с кучей рекурсивного кода или непонятно-зачем-хитрой работой со стеком) может начать падать. Осторожность не повредит. Вы предупреждены. Делайте бэкапы. Но 10M под стек — это, в большинстве случаев, очень много)

Мне показался оптимальным размер 2М. Экстремалы и экспериментаторы могут снижать и дальше (пробовал, у меня и на 32К все работало прекрасно), но там выигрыш уже небольшой получается, а риск возрастает, смысла мало вообщем. Хотя — пробуйте.

В принципе, запуск ulimit для всех процессов — довольно грубо. Для более тонкой настройки можно(задолбаться) править скрипты запуска отдельных демонов. Также у некоторых программ можно в конфигах менять память, которую они будут выделять на стек треда, пример — apache, директива ThreadStackSize для mpm_worker. Собственно говоря, у меня апач и был настроен в режиме worker (php — через fastcgi, если что), а память на стек ограничивалась с помощью ThreadStackSize без ulimit (то снижение в 2 раза было за счет mysql с InnoDB, fastcgi-процессов php, mail-сервера и всякой мелочи).

Для тестирования всего этого дела, если боязно лезть сразу в /etc/init.d/rc, можете
1) посмотреть, сколько занимает в памяти какой-нибудь процесс,
2) в шелле ввести ulimit -s <сколько-нибудь, в килобайтах>,
3) перезапустить процесс (что-нибудь в духе /etc/init.d/mysql restart)
4) посмотреть еще раз, сколько теперь занимает, и проверить, что все работает

Мысли


В итоге мы имеем: пользователи OpenVZ расплачиваются кучей оперативной памяти за возможность когда-нибудь (черти когда) запустить редкую хитрую программу, тогда как всем остальным это не стоит ничего. Поэтому поступаем, как мне кажется, логично: при виртуализации OpenVZ снижаем макс. глубину стека до 1-2М. На всяких HP-UX (который я, правда, в глаза не видел), например, 64К, и не плачут. А от снижения макс. глубины стека освобождается куча оперативной памяти для более важных штук.

Критика и замечания приветствуется.
Коробов Михаил @kmike
карма
334,7
рейтинг 0,0
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Спецпроект

Самое читаемое Администрирование

Комментарии (45)

  • +4
    Апач с 15k витхостов требует ulimit -s unlimited
    Хотя 15k на vps не будут пускать, тем не менее — учтите, что чем больше энтропия, тем выше требования к стеку
    • +2
      Если у вас на апаче 15к виртхостов, то у вас что-то совсем не то с бизнес-логикой. Не представляю ситуации, когда может понадобится даже 50 виртхостов, ну кроме хостинговых серверов.
      • 0
        Хостинговый сервер вполне может быть на VPS, если это сильно начинающий хостер :)

        Но согласен. Как только количество пользователей перевалит хотя бы за 100 человек. Уже пора съезжать на отдельный сервер. Пусть даже и на какой-нибудь бюджетный.
      • +1
        50 на сервак? Легко. У меня в университете их примерно 30 (на одной машине). И это мы еще ограничиваем запросы и фантазии руководства и пользователей. Ни разу не хостинговая компания.

        • НЛО прилетело и опубликовало эту надпись здесь
          • +1
            Спасибо, но отвечал я на комментарий с 50 хостами без _К_

            Для 50К тоже вижу применение сходу — какой-нибудь киберсквоттер с рекламными страницами. Что тоже врое как не хостинг.
            • НЛО прилетело и опубликовало эту надпись здесь
      • 0
        Хостинг, все верно.
    • 0
      учту, спасиб
  • +4
    в шелле ввести uname -s

    Наверное, ulimit ?! :)
    • 0
      упс, спасибо
  • +1
    У меня без настроек «ulimit -s» выдаёт 8192, значит всё ок? :)
    • +3
      Понял, что не ок, дурак, исправлюсь.
  • +1
    Кроме снижения потребления оперативной памяти в OpenVZ (РБК Хостинг), есть еще параметры user beancounters, которых тоже может нехватать.

    Я решил все эти проблемы следующим образом:

    Убил Apache, поставил Nginx, уменьшил в nginx sndbuf до 16k, так как именно его мне нехватало при увеличении количества соединений до 1000.

    В настоящий момент система спокойно поддерживает до 1000 соединий (лимит по tcp сокетам хостинга)
    • 0
      да, и самое главное на VPS, выключить keep-alive.
      • +1
        У Вас же nginx, какая разница включать или нет? Процессы его дёшевы.
        • 0
          tcpsockets <= 1000, если keep-alive не урезать, то они кончаются быстрее, чем все остальные ресурсы VPS.
      • 0
        а TIME_WAIT там не учитываются, или вообще не поддерживаются? Они же остаются, когда сервер закрывает соединение.
        А еще нельзя использовать частые соединения на localhost (то есть не использовать схему фронтенд-бэкенд, использовать только постоянные соединения с БД, итд)
        Вот обычный хостинг (порты 81, 85 — это апач)

        tcp 0 0 hosting:80 79.165.234.182:1372 TIME_WAIT
        tcp 0 0 127.0.0.1:81 127.0.0.1:35786 TIME_WAIT
        tcp 0 0 127.0.0.1:85 127.0.0.1:33738 TIME_WAIT
        tcp 0 0 127.0.0.1:85 127.0.0.1:33482 TIME_WAIT
        tcp 0 0 127.0.0.1:85 127.0.0.1:33226 TIME_WAIT
        tcp 0 0 hosting:80 87.242.74.101:42107 TIME_WAIT


        В результате nginx-apache выливается в
        $ netstat -atn | wc -l
        1430
        Cредняя недельная нагрузка апача 6.08 requests/sec
        Но я почти уверен, что в пиковые моменты использованных сокетов до 10 раз больше.
        • 0
          в nginx есть возможность уменьшить количество TIME_WAIT с помощью опции reset_timedout_connection
  • 0
    На Virtuozzo/OpenVZ своп доступен, но только по желанию хостера и только по принципу «всем или никому». По крайней мере, два года назад был доступен :) Так что надежнее определять платформу по uname -a.
    • 0
      Хм, по uname -a у меня, например, никакого намека на используемую систему виртуализации.
      Насчет свопа — точно. Эмпирическое правило, что я написал, не всегда работает)
      Проще узнать у хостера)
      • 0
        Если ядра нет, если есть /proc/user_beancounters — значит OpenVZ (или Virtuozzo).
      • +1
        моя очередь хмыкать :)
        в бытность мою админов VPS-хостинга с виртуозой uname стабильно писал 2.6.9-bla-bla-vz
        он ведь отдается с хостовой системы, а под virtuozzo/openvz ядро патчится, и version.h в т.ч.
        • +2
          Сейчас, как правило, в ядре будет присутствовать суффикс «stab», если vzzo/openvz.
          • 0
            ХМ, не знал, и вправду)
    • 0
      убрал то примечание про своп.
      Короче правильнее было бы «если свопа нет — значит OpenVZ».
      • +1
        … или просто нет свопа.
        • 0
          угу.
        • 0
          теоретически угу)
  • +2
    Лимиты для пользователя или группы штатно можно задавать в /etc/security/limits.conf.
  • 0
    Глупый вопрос: Зачем брать VPS на VZ при наличии вменяемых предложений на Xen?
    • +1
      Потому что предложения на OpenVZ дешевле — там память не жёстко распределяется, отсюда возможность оверселлинга и дешевизна.
  • НЛО прилетело и опубликовало эту надпись здесь
    • 0
      Применимо аж на все 200%. Но дело в другом: связать-то её ни с чем не свяжут, но в квоту к вам — запишут обязательно. Чтобы не было идиотских ситуаций когда вы успешно выделили 200M, а при попытке использовать 110M — программка в кору падает.
    • 0
      с точки зрения пользователя это справедливо для Xen и Linux без виртуализации, но неверно для OpenVZ, с этим и боремся
  • 0
    полезно, интересно как это в Русониксе
    • 0
      Почти уверен, что точно так же, у них там Virtuozzo.
      С тем, чтобы хостер как-то настраивал ulimit -s, ни разу не встречался.
  • 0
    Блин, это не надо пихать в инит-скрипты. Для этого есть /etc/security/limits.conf! Там же можно настроить ограничения по группам, чтобы то, что нужно, точно не упало!
    • 0
      Раз уж второй раз пишут, и эмоционально) Вот что мне по этому поводу думается.
      1. Если нужные процессы запускаются через PAM от отдельных пользователей-групп, то решение с limits.conf хорошее.
      2. Не везде есть-используется PAM. Если его нет, или где-то права даются минуя PAM, то /etc/security/limits.conf ничего не ограничивает. У меня PAM не установлен, например.
      3. «Не надо» — не аргумент) Решение «пихать все в инит-скрипты» — одно из возможных, оно простое, универсальное и работает. +Для применения индивидуальных ограничений процессы не обязательно должны запускаться от разных пользователей-групп. Но я на этом способе не настаиваю, статья не об этом совсем)
  • 0
    Человек дал вам тему для размышления, а не четкие действия к исполнению.
    Для каждой задачи можно использовать по своему.
  • 0
    Только что прописал ulimit -s 1024 в /etc/init.d/rc До этого VPS висел, жутко не хватало памяти. Сейчас вроде нагрузка упала. Было 250-270 Мб, стало 140-150. Немного растет постепенно, но не смертельно. Спасибо!
    • 0
      Ничего не упало? Всё работает как прежде?
  • 0
    покажите ламеру пожалуйста, куда вы вписали ulimit -s 1024 в файле /etc/init.d/rc. и перезагружать только весь сервер или apache, mysql
    • 0
      сорри за панику, разобрался
  • 0
    Это только на дебайне, или на убунту тоже работает?
    Просто прописал, перезапустил, но ничего в памяти не изменилось.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.