17.4. Управление ресурсами ядра#

17.4. Управление ресурсами ядра

17.4. Управление ресурсами ядра #

Tantor BE иногда может исчерпывать различные ограничения операционной системы, особенно когда на одной системе работает несколько копий сервера или в очень больших установках. В этом разделе объясняются ресурсы ядра, используемые Tantor BE, и шаги, которые можно предпринять для решения проблем, связанных с потреблением ресурсов ядра.

17.4.1. Общая память и семафоры #

Для работы Tantor BE требуется, чтобы операционная система предоставляла возможности обмена данными между процессами (IPC), в частности общую память и семафоры. В системах, на базе Unix, обычно предоставляются System V IPC, POSIX IPC или оба вида. Windows имеет собственную реализацию этих возможностей, о которой здесь не рассказывается.

По умолчанию, Tantor BE выделяет очень малое количество общей памяти System V, и гораздо больше анонимной общей памяти mmap. Также можно использовать одну большую область общей памяти System V (см. shared_memory_type). Кроме того, при запуске сервера создается значительное количество семафоров, которые могут быть как вида System V, так и POSIX. В настоящее время на системах Linux и FreeBSD используются POSIX-семафоры, в то время как на других платформах используются семафоры System V.

Функции IPC System V обычно ограничены глобальными пределами выделения. Когда Tantor BE превышает один из этих пределов, сервер откажется запускаться и должен выдать информативное сообщение об ошибке, описывающее проблему и что с ней делать. (См. также Раздел 17.3.1). Соответствующие параметры ядра имеют одинаковые имена в разных системах; Таблица 17.1 дает обзор. Однако, методы их установки различаются. Ниже приведены рекомендации для некоторых платформ.

Таблица 17.1. System V IPC Параметры

ИмяОписаниеЗначения, необходимые для запуска одного экземпляра Tantor BE
SHMMAXМаксимальный размер сегмента общей памяти (в байтах)не менее 1 кБ, но по умолчанию обычно гораздо больше
SHMMINМинимальный размер сегмента общей памяти (в байтах)1
SHMALLОбщее количество доступной общей памяти (в байтах или страницах)то же самое, что и SHMMAX, если в байтах, или ceil(SHMMAX/PAGE_SIZE), если в страницах, плюс место для других приложений
SHMSEGМаксимальное количество сегментов общей памяти на процесстребуется только 1 сегмент, но значение по умолчанию гораздо выше
SHMMNIМаксимальное количество общих сегментов памяти в системеаналогично SHMSEG, плюс место для других приложений
SEMMNIМаксимальное количество идентификаторов семафоров (т.е. наборов)по крайней мере ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 16) плюс место для других приложений
SEMMNSМаксимальное количество семафоров в системеceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 16) * 17 плюс место для других приложений
SEMMSLМаксимальное количество семафоров в наборене менее 17
SEMMAPКоличество записей в карте семафоровсм. текст
SEMVMXМаксимальное значение семафоране менее 1000 (По умолчанию часто устанавливается значение 32767; не изменяйте, если необходимо)

Tantor BE необходимо несколько байтов общей памяти System V (обычно 48 байтов на 64-битных платформах) для каждой копии сервера. На большинстве современных операционных систем достаточно легко выделить такой объем памяти. Однако, если вы запускаете много копий сервера или явно указываете серверу использовать большие объемы общей памяти System V (см. shared_memory_type и dynamic_shared_memory_type), может потребоваться увеличить значение SHMALL, которое представляет собой общий объем общей памяти System V в системе. Обратите внимание, что на многих системах SHMALL измеряется в страницах, а не в байтах.

Меньше вероятность возникновения проблем вызывает минимальный размер для общих сегментов памяти (SHMMIN), который должен быть не более примерно 32 байт для Tantor BE (обычно это всего лишь 1). Максимальное количество сегментов в системе (SHMMNI) или на процесс (SHMSEG) маловероятно вызовет проблемы, если они установлены в ноль.

При использовании семафоров System V, Tantor BE использует один семафор на каждое разрешенное соединение (max_connections), разрешенный процесс автovacuum (autovacuum_max_workers), разрешенный процесс отправки WAL (max_wal_senders), и разрешенный фоновый процесс (max_worker_processes), в наборах по 16. Каждый такой набор будет также содержать 17-й семафор, который содержит магическое число, для обнаружения коллизий с наборами семафоров, используемыми другими приложениями. Максимальное количество семафоров в системе задается параметром SEMMNS, который, следовательно, должен быть как минимум таким же высоким, как max_connections плюс autovacuum_max_workers плюс max_wal_senders, плюс max_worker_processes, плюс один дополнительный для каждых 16 разрешенных соединений плюс рабочих процессов (см. формулу в Таблица 17.1). Параметр SEMMNI определяет предел на количество наборов семафоров, которые могут существовать в системе одновременно. Следовательно, этот параметр должен быть как минимум ceil((max_connections + autovacuum_max_workers + max_wal_senders + max_worker_processes + 6) / 16). Снижение количества разрешенных соединений является временным решением для сбоев, которые обычно формулируются запутанно как Нет места на устройстве, из функции semget.

В некоторых случаях может потребоваться увеличить значение параметра SEMMAP до значения, по крайней мере, порядка значения SEMMNS. Если в системе присутствует этот параметр (многие системы его не имеют), он определяет размер карты ресурсов семафоров, в которой каждый непрерывный блок доступных семафоров требует записи. При освобождении набора семафоров он либо добавляется к существующей записи, смежной с освобожденным блоком, либо регистрируется в новой записи карты. Если карта заполнена, освобожденные семафоры теряются (до перезагрузки). Фрагментация пространства семафоров со временем может привести к меньшему количеству доступных семафоров, чем должно быть.

Различные другие настройки, связанные с отменой семафора, такие как SEMMNU и SEMUME, не влияют на Tantor BE.

При использовании семафоров POSIX, количество необходимых семафоров такое же, как и для System V, то есть один семафор на каждое разрешенное соединение (max_connections), разрешенный процесс автovacuum (autovacuum_max_workers), разрешенный процесс отправки WAL (max_wal_senders), и разрешенный фоновый процесс (max_worker_processes). На платформах, где этот вариант предпочтителен, нет конкретного ограничения ядра на количество семафоров POSIX.

AIX

Необходимости в особой настройке для таких параметров, как SHMMAX, не должно возникать, так как, по-видимому, они настроены таким образом, чтобы позволить использовать всю память в качестве общей памяти. Такая конфигурация обычно используется для других баз данных, таких как DB/2.

Может быть необходимо изменить глобальную информацию ulimit в файле /etc/security/limits, так как значения по умолчанию для жестких ограничений размера файлов (fsize) и количества файлов (nofiles) могут быть слишком низкими.

FreeBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv. Системные семафоры V не используются на этой платформе.

Настройки IPC по умолчанию можно изменить с помощью интерфейсов sysctl или loader. Следующие параметры можно установить с помощью sysctl:

# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

Если вы установили shared_memory_type в значение sysv, вам также может потребоваться настроить ядро для блокировки System V общей памяти в оперативной памяти и предотвращения ее выгрузки в подкачку. Это можно сделать с помощью параметра sysctl kern.ipc.shm_use_phys.

Если вы работаете в тюрьме FreeBSD, вы должны установить параметр sysvshm в значение new, чтобы у него было собственное отдельное пространство имен System V для общей памяти. (До FreeBSD 11.0 было необходимо разрешить общий доступ к пространству имен IPC хоста из тюрем и принимать меры для избежания конфликтов).

NetBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в значение sysv. Обычно вам потребуется увеличить значения kern.ipc.semmni и kern.ipc.semmns, так как значения по умолчанию в NetBSD для этих параметров слишком малы и вызывают дискомфорт.

Параметры IPC могут быть настроены с помощью команды sysctl, например:

# sysctl -w kern.ipc.semmni=100

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

Если вы установили shared_memory_type в значение sysv, вам также может потребоваться настроить ядро для блокировки System V общей памяти в оперативной памяти и предотвращения ее выгрузки в подкачку. Это можно сделать с помощью параметра sysctl kern.ipc.shm_use_phys.

OpenBSD

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv. Обычно вам захочется увеличить kern.seminfo.semmni и kern.seminfo.semmns, так как значения по умолчанию в OpenBSD для этих параметров слишком малы и вызывают дискомфорт.

Параметры IPC могут быть настроены с помощью команды sysctl, например:

# sysctl kern.seminfo.semmni=100

Чтобы сделать эти настройки постоянными после перезагрузки, измените файл /etc/sysctl.conf.

Linux

Настройки общей памяти по умолчанию обычно достаточно хороши, если только вы не установили shared_memory_type в sysv, и даже тогда только в старых версиях ядра, которые поставлялись с низкими значениями по умолчанию. Системные семафоры System V не используются на этой платформе.

Настройки размера общей памяти можно изменить через интерфейс sysctl. Например, чтобы разрешить 16 ГБ:

$ sysctl -w kernel.shmmax=17179869184
$ sysctl -w kernel.shmall=4194304

Чтобы сделать эти настройки постоянными после перезагрузки, см. /etc/sysctl.conf.

macOS

Настройки общей памяти и семафоров по умолчанию обычно достаточно хороши, если вы не установили shared_memory_type в значение sysv.

Рекомендуемый способ настройки общей памяти в macOS - создать файл с именем /etc/sysctl.conf, содержащий присваивания переменных, например:

kern.sysv.shmmax=4194304
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=1024

Обратите внимание, что в некоторых версиях macOS все пять параметров общей памяти должны быть установлены в файле /etc/sysctl.conf, иначе значения будут проигнорированы.

SHMMAX может быть установлено только как кратное числу 4096.

SHMALL измеряется в страницах размером 4 кБ на данной платформе.

Возможно изменить все, кроме SHMMNI, на лету, используя sysctl. Однако лучше всего настроить предпочтительные значения через /etc/sysctl.conf, чтобы значения сохранялись после перезагрузки.

Solaris
illumos

Настройки общей памяти и семафоров по умолчанию обычно оптимальны для большинства приложений Tantor BE. В Solaris значение SHMMAX составляет одну четверть от общего объема RAM системы. Чтобы дополнительно настроить это значение, используйте настройки проекта, связанные с пользователем postgres. Например, выполните следующую команду от имени пользователя root:

projadd -c "PostgreSQL DB User" -K "project.max-shm-memory=(privileged,8GB,deny)" -U postgres -G postgres user.postgres

Эта команда добавляет проект user.postgres и устанавливает максимальный объем общей памяти для пользователя postgres в 8 ГБ. Изменения вступят в силу при следующем входе пользователя или при перезапуске Tantor BE (не перезагрузке). Предполагается, что Tantor BE запущен пользователем postgres в группе postgres. Перезагрузка сервера не требуется.

Другие рекомендуемые изменения настроек ядра для серверов баз данных, которые будут иметь большое количество соединений, включают:

project.max-shm-ids=(priv,32768,deny)
project.max-sem-ids=(priv,4096,deny)
project.max-msg-ids=(priv,4096,deny)

Кроме того, если вы запускаете Tantor BE внутри зоны, вам может потребоваться увеличить лимиты использования ресурсов зоны. См. "Глава 2: Проекты и задачи" в Руководство системного администратора для получения дополнительной информации о projects и prctl.

17.4.2. systemd RemoveIPC #

Если systemd используется, необходимо обратить внимание на то, чтобы ресурсы IPC (включая общую память) не были преждевременно удалены операционной системой. Это особенно важно при установке PostgreSQL из исходного кода. Пользователи пакетов распространения PostgreSQL меньше подвержены этому влиянию, так как пользователь postgres обычно создается как системный пользователь.

Настройка RemoveIPC в logind.conf определяет, будут ли удалены IPC-объекты при полном выходе пользователя. Системные пользователи не подпадают под это правило. По умолчанию эта настройка в стандартной версии systemd включена, но в некоторых операционных системах она отключена.

Типичным наблюдаемым эффектом при включении этой настройки является то, что объекты общей памяти, используемые для параллельного выполнения запросов, удаляются на видимо случайные моменты времени, что приводит к ошибкам и предупреждениям при попытке открытия и удаления их, например

WARNING:  could not remove shared memory segment "/PostgreSQL.1450751626": No such file or directory

Различные типы объектов IPC (общая память против семафоров, System V против POSIX) обрабатываются немного по-разному systemd, поэтому можно заметить, что некоторые ресурсы IPC не удаляются так же, как другие. Однако не рекомендуется полагаться на эти тонкие различия.

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

Что такое системный пользователь определяется во время компиляции systemd из настройки SYS_UID_MAX в файле /etc/login.defs.

Упаковочные и развертывающие скрипты должны быть осторожными при создании пользователя postgres в качестве системного пользователя с использованием команды useradd -r, adduser --system или аналогичной.

В противном случае, если учетная запись пользователя была создана неправильно или не может быть изменена, рекомендуется установить

RemoveIPC=no

в файле /etc/systemd/logind.conf или другом соответствующем файле конфигурации.

Предостережение

По крайней мере, одно из этих двух условий должно быть обеспечено, иначе сервер PostgreSQL будет очень ненадежным.

17.4.3. Ограничения ресурсов #

Unix-подобные операционные системы применяют различные виды ограничений ресурсов, которые могут помешать работе вашего сервера Tantor BE. Особенно важны ограничения на количество процессов на пользователя, количество открытых файлов на процесс и объем памяти, доступный каждому процессу. Каждый из них имеет "жесткий" и "мягкий" пределы. Мягкий предел - это то, что на самом деле учитывается, но его можно изменить пользователем до жесткого предела. Жесткий предел может быть изменен только root-пользователем. Вызов системы setrlimit отвечает за установку этих параметров. Встроенная команда оболочки ulimit (для оболочек Bourne) или limit (для оболочки csh) используется для управления ограничениями ресурсов из командной строки. В системах, основанных на BSD, файл /etc/login.conf управляет различными ограничениями ресурсов, установленными при входе в систему. См. документацию операционной системы для получения подробной информации. Соответствующие параметры - maxproc, openfiles и datasize. Например:

default:\
...
        :datasize-cur=256M:\
        :maxproc-cur=256:\
        :openfiles-cur=256:\
...

(-cur - это мягкий предел. Добавьте -max для установки жесткого предела).

Ядра также могут иметь системные ограничения на некоторые ресурсы.

  • На Linux параметр ядра fs.file-max определяет максимальное количество открытых файлов, которое поддерживает ядро. Его можно изменить с помощью sysctl -w fs.file-max=N. Чтобы сохранить настройку после перезагрузки, добавьте присваивание в /etc/sysctl.conf. Максимальное ограничение файлов на процесс устанавливается во время компиляции ядра; см. /usr/src/linux/Documentation/proc.txt для получения дополнительной информации.

Сервер Tantor BE использует один процесс на соединение, поэтому вам следует предусмотреть не менее столько процессов, сколько разрешено соединений, в дополнение к тому, что вам нужно для остальной части вашей системы. Обычно это не является проблемой, но если вы запускаете несколько серверов на одной машине, могут возникнуть проблемы с ресурсами.

Ограничение по умолчанию на количество открытых файлов в фабрике часто устанавливается на "социально дружественные" значения, которые позволяют множеству пользователей сосуществовать на одной машине, не используя неподходящую долю системных ресурсов. Если вы запускаете много серверов на одной машине, то это, возможно, то, что вам нужно, но на выделенных серверах вы можете захотеть увеличить это ограничение.

С другой стороны, некоторые системы позволяют отдельным процессам открывать большое количество файлов; если это делают более нескольких процессов, то легко можно превысить системное ограничение. Если вы обнаружите, что это происходит и вы не хотите изменять системное ограничение, вы можете установить параметр конфигурации Tantor BE max_files_per_process, чтобы ограничить количество открытых файлов.

Еще одно ограничение ядра, которое может вызвать беспокойство при поддержке большого количества клиентских подключений, — это максимальная длина очереди подключений сокета. Если в течение очень короткого периода поступит больше запросов на подключение, чем это значение, некоторые из них могут быть отклонены до того, как сервер Tantor BE сможет обработать запросы, и эти клиенты получат неинформативные ошибки подключения, такие как Ресурс временно недоступен или Подключение отклонено. По умолчанию ограничение длины очереди составляет 128 на многих платформах. Чтобы увеличить его, настройте соответствующий параметр ядра через sysctl, затем перезапустите сервер Tantor BE. Параметр называется по-разному: net.core.somaxconn на Linux, kern.ipc.soacceptqueue на новых версиях FreeBSD и kern.ipc.somaxconn на macOS и других вариантах BSD.

17.4.4. Перераспределение памяти в Linux #

По умолчанию, поведение виртуальной памяти в Linux не является оптимальным для Tantor BE. Из-за того, как ядро реализует перераспределение памяти, ядро может завершить работу постмастера Tantor BE (супервизора серверного процесса), если требования к памяти как у Tantor BE, так и у другого процесса приведут к исчерпанию виртуальной памяти системы.

Если это произойдет, вы увидите сообщение ядра, которое будет выглядеть примерно так (обратитесь к документации и конфигурации вашей системы, чтобы узнать, где искать такое сообщение):

Out of Memory: Killed process 12345 (postgres).

Это указывает на то, что процесс postgres был завершен из-за нехватки памяти. Хотя существующие подключения к базе данных будут продолжать функционировать нормально, новые подключения не будут приниматься. Для восстановления необходимо перезапустить Tantor BE.

Один из способов избежать этой проблемы - запустить Tantor BE на машине, где вы можете быть уверены, что другие процессы не будут использовать всю память. Если память ограничена, увеличение пространства подкачки операционной системы может помочь избежать проблемы, поскольку убийца процессов из-за нехватки памяти (OOM) вызывается только тогда, когда физическая память и пространство подкачки исчерпаны.

Если сама Tantor BE является причиной нехватки памяти в системе, вы можете избежать проблемы, изменив конфигурацию. В некоторых случаях может помочь снижение параметров конфигурации, связанных с памятью, особенно shared_buffers, work_mem и hash_mem_multiplier. В других случаях проблема может быть вызвана разрешением слишком большого количества подключений к самому серверу базы данных. Во многих случаях лучше уменьшить max_connections и вместо этого использовать внешнее программное обеспечение для пула подключений.

Возможно изменить поведение ядра так, чтобы оно не перераспределяло память. Хотя эта настройка не предотвратит полное вызова OOM killer, она значительно снизит вероятность его вызова и, следовательно, обеспечит более надежное поведение системы. Для этого выбирается строгий режим перераспределения памяти с помощью sysctl:

sysctl -w vm.overcommit_memory=2

или разместите эквивалентную запись в /etc/sysctl.conf. Также можно изменить связанный параметр vm.overcommit_ratio. Подробности см. в документации ядра файл https://www.kernel.org/doc/Documentation/vm/overcommit-accounting.

Другой подход, который можно использовать с изменением или без изменения параметра vm.overcommit_memory, заключается в установке процесс-специфического значения приоритета коррекции OOM для процесса постмастер в значение -1000, тем самым гарантируя, что он не будет выбран OOM-убийцей. Самый простой способ сделать это - выполнить следующую команду

echo -1000 > /proc/self/oom_score_adj

в Tantor BE стартовом скрипте непосредственно перед вызовом postgres. Обратите внимание, что это действие должно быть выполнено от имени root, иначе оно не будет иметь эффекта; поэтому скрипт запуска, принадлежащий root, является самым простым местом для этого. Если вы сделаете это, вам также следует установить эти переменные окружения в стартовом скрипте перед вызовом postgres:

export PG_OOM_ADJUST_FILE=/proc/self/oom_score_adj
export PG_OOM_ADJUST_VALUE=0

Эти настройки приведут к тому, что дочерние процессы постмастер будут работать с нормальной настройкой OOM score, равной нулю, чтобы OOM -убийца все еще мог на них нацеливаться при необходимости. Вы можете использовать другое значение для PG_OOM_ADJUST_VALUE, если нужно, чтобы дочерние процессы работали с другой настройкой OOM score. (PG_OOM_ADJUST_VALUE также можно опустить, в этом случае оно устанавливается по умолчанию равным нулю). Если вы не установите PG_OOM_ADJUST_FILE, дочерние процессы будут работать с той же настройкой OOM score, что и постмастер, что не рекомендуется, поскольку весь смысл заключается в том, чтобы обеспечить постмастеру предпочтительную настройку.

17.4.5. Огромные страницы Linux #

Использование больших страниц уменьшает накладные расходы при использовании больших смежных блоков памяти, как это делает Tantor BE, особенно при использовании больших значений shared_buffers. Чтобы использовать эту функцию в Tantor BE, вам необходим ядро с CONFIG_HUGETLBFS=y и CONFIG_HUGETLB_PAGE=y. Вам также потребуется настроить операционную систему для предоставления достаточного количества больших страниц нужного размера. Параметр, вычисляемый во время выполнения, shared_memory_size_in_huge_pages сообщает количество требуемых больших страниц. Этот параметр можно просмотреть до запуска сервера с помощью команды postgres такой как:

$ postgres -D $PGDATA -C shared_memory_size_in_huge_pages
3170
$ grep ^Hugepagesize /proc/meminfo
Hugepagesize:       2048 kB
$ ls /sys/kernel/mm/hugepages
hugepages-1048576kB  hugepages-2048kB

В этом примере значение по умолчанию составляет 2 МБ, но вы также можете явно запросить либо 2 МБ, либо 1 ГБ с помощью huge_page_size, чтобы адаптировать количество страниц, рассчитанных по shared_memory_size_in_huge_pages. В этом примере нам необходимо как минимум 3170 огромных страниц, но более крупное значение будет соответствующим, если другие программы на машине также нуждаются в огромных страницах. можно установить это с помощью:

# sysctl -w vm.nr_hugepages=3170

Не забудьте добавить эту настройку в /etc/sysctl.conf, чтобы она применялась после перезагрузки. Для нестандартных размеров больших страниц можно использовать вместо этого:

# echo 3170 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Также возможно указать эти настройки при загрузке системы, используя параметры ядра, такие как hugepagesz=2M hugepages=3170.

Иногда ядро не может сразу выделить желаемое количество больших страниц из-за фрагментации, поэтому может потребоваться повторить команду или перезагрузить систему. (Сразу после перезагрузки большая часть памяти машины должна быть доступна для преобразования в большие страницы). Чтобы проверить ситуацию с выделением больших страниц определенного размера, используйте:

$ cat /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages

Может потребоваться также предоставить пользователю операционной системы сервера баз данных разрешение на использование огромных страниц, установив vm.hugetlb_shm_group через sysctl и/или предоставив разрешение на блокировку памяти с помощью ulimit -l.

По умолчанию Tantor BE использует huge pages, если это возможно, с размером huge page, установленным по умолчанию в системе, и в случае неудачи переходит на обычные страницы. Чтобы обеспечить использование huge pages, вы можете установить huge_pages в on в файле postgresql.conf. Обратите внимание, что с этой настройкой Tantor BE не сможет запуститься, если недостаточно huge pages.

Для подробного описания функции Linux huge pages ознакомьтесь с https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.