6. Управление памятью
HAProxy использует простое и быстрое управление памятью на основе пулов. Поскольку он работает с небольшим числом различных типов объектов, гораздо эффективнее брать новые объекты из пула, уже содержащего объекты подходящего размера, чем вызывать malloc() для каждого отдельного размера. Пулы организованы как стек, или LIFO: при выделении используются недавно освобождённые объекты, которые ещё находятся в кэшах CPU. Пулы близких размеров объединяются, чтобы ограничить фрагментацию памяти.
По умолчанию, поскольку приоритет отдаётся производительности, каждый освобождённый объект возвращается в свой исходный пул, а выделенная память под объекты никогда не освобождается, так как ожидается их скорое повторное использование.
В CLI можно проверить использование памяти пулами с помощью команды “show pools”:
Имя пула носит лишь справочный характер: это имя первого типа объектов, использовавшего данный пул. Размер в скобках — размер объектов в этом пуле. Размеры объектов всегда округляются вверх до ближайшего числа, кратного 16 байтам. Выводятся текущее число выделенных объектов и соответствующее количество байтов, что позволяет легко определить, какой пул потребляет больше всего памяти. Число объектов, используемых в данный момент, также приводится в поле “used”. Разница между “allocated” и “used” соответствует освобождённым объектам, доступным для немедленного использования. Адрес в конце строки — это адрес пула, а следующее за ним число — индекс пула, если он существует; если индекс не назначен, выводится -1.
Объём памяти, выделяемой на процесс, можно ограничить параметром командной строки “-m”, указав после него число мегабайт. Он охватывает всё адресуемое пространство процесса, включая память некоторых библиотек и стек, но обеспечивает надёжное ограничение при построении системы с ограниченными ресурсами. Он работает так же, как “ulimit -v” в системах, где эта команда доступна, или “ulimit -d” в остальных.
Если выделить память не удалось из-за достижения лимита или из-за нехватки памяти в системе, haproxy сначала освобождает все доступные объекты во всех пулах, а затем снова пытается выделить память. Этот механизм освобождения неиспользуемой памяти можно запустить, отправив процессу haproxy сигнал SIGQUIT.
При перезагрузке конфигурации процесс, перешедший в состояние плавной остановки, также автоматически очищает память после освобождения каждого соединения, чтобы высвободить как можно больше памяти для нового процесса.