Вопрос или проблема
Я столкнулся с ошибкой выделения памяти в nginx. Я настроил обратный прокси для нескольких сайтов на моем nginx, который использую как простой балансировщик нагрузки между двумя узловыми серверами. Типичная конфигурация для сайта выглядит следующим образом:
upstream backend {
ip_hash;
server <node-ip>;
server <another-node-ip>;
}
server {
server_name domain.subdomain.com;
# ОГРОМНАЯ куча правил перенаправления
include /etc/nginx/sites-available/root;
location / {
proxy_pass http://backend ;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
У меня 12 сайтов с конфигурацией, подобной вышеуказанной. Как вы видите, конфигурация содержит include
другого файла – sites-available/root
. Этот файл состоит из многих директив include
для других файлов:
include /etc/nginx/sites-available/rules1;
include /etc/nginx/sites-available/rules2;
include /etc/nginx/sites-available/rules3;
...
include /etc/nginx/sites-available/rules16;
Каждый файл правил содержит множество правил перенаправления, например:
if ($request_uri ~* ^/some-url$) {
return 302 /some-another-url/;
}
или
location ~ some-url {
return 302 "some-another-url";
}
Общее количество правил перенаправления составляет около 2300. Я включил файл root
в конфигурации всех 12 сайтов. После этого время от времени я получаю информационное сообщение в /var/log/nginx/error.log
:
[info] 23721#23721: Используется 32768KiB общей памяти для push модуля в /etc/nginx/nginx.conf:66
Основная проблема заключается в том, что иногда команда service nginx reload
завершается с ошибками в журнале:
[alert] 22164#22164: fork() не удался при создании “worker process” (12: Невозможно выделить память)
2018/10/09 03:10:06[alert] 22164#22164: sendmsg() не удался (9: Неверный дескриптор файла)
Проблема исчезает, если я исключу правила перенаправления из конфигурации. Nginx настроен на простой экземпляр AWS t2.small с Ubuntu 16.04. У него 1 ГБ ОЗУ, и я вижу (с помощью free -m
), что, по крайней мере, половина памяти свободна. У меня стандартный nginx.conf. Так что вопрос в том, как избежать ошибки cannot allocate memory
, которая вызвана огромным количеством правил перенаправления?
Этот вопрос изначально был опубликован здесь. Я подумал, что кто-то здесь может знать ответ. Извините за дублирование.
Разделите файл на более мелкие части, если он большой. У меня был файл размером 1.8 МБ с около 20 000 перенаправлений, который экземпляр с низким объемом памяти не мог обработать и выдал ошибку, которую вы получили. Я исправил это следующим образом:
mkdir /etc/nginx/conf.d/redirects
split -l 1000 redirect_file redirect_folder/
… а затем просто включил папку в конфигурацию сервера, например:
server {
listen 127.0.0.1:80
...
include conf.d/redirects/*;
...
}
Nginx затем загружается нормально. Я лишь догадываюсь, но у меня такое предположение, что nginx освобождает память, используемую для чтения файла, как только он его загрузил, и при наличии многих мелких файлов потребление памяти значительно ниже, чем при загрузке одного большого. Но, как я уже сказал, это чисто предположение, я могу ошибаться.
Ответ или решение
Проблема, с которой вы столкнулись, связана с большой нагрузкой на память, вызванной обилием правил перенаправления в конфигурации Nginx. Давайте детально разберем причины возникновения ошибки Cannot allocate memory
и возможные пути ее решения.
Причины возникновения ошибки
-
Обилие правил перенаправления: Вы упомянули, что у вас есть около 2300 правил перенаправления, что само по себе может быть довольно ресурсоемким, особенно на сервере с ограниченными ресурсами, таких как ваш AWS t2.small с 1 ГБ оперативной памяти.
-
Размер конфигурационных файлов: При использовании большого количества правил в едином конфигурационном файле Nginx может потребоваться значительное количество памяти для обработки и загрузки этих правил в память при перезагрузке службы.
-
Архитектура памяти Nginx: Nginx использует память для хранения различных структур данных. Когда правила и конфигурации большие, этот процесс может исчерпать доступную память, даже если общее количество свободной оперативной памяти на сервере кажется достаточным.
Решения
-
Разделение конфигурационных файлов:
Как вы уже упомянули, разумным шагом будет разделить ваши правила перенаправления на меньшие файлы. Это может снизить нагрузку на память. Например, создать каталог/etc/nginx/conf.d/redirects
и распределить ваши правила по нескольким файлам, включив каждый из них в основной конфигурационный файл:server { server_name domain.subdomain.com; # быть уверенным, что правила разделены на меньшие части include /etc/nginx/conf.d/redirects/*.conf; location / { proxy_pass http://backend; ... } }
-
Оптимизация правил перенаправления:
Попробуйте оптимизировать существующие правила. Например, если некоторые правила могут быть обработаны более эффективно, вы можете уменьшить их количество, комбинируя похожие URL или используя регулярные выражения более рационально. -
Увеличение ресурсов сервера:
Если возможно, рассмотрите возможность обновления конфигурации вашего AWS-инстанса для увеличения объема оперативной памяти. Переход на более мощный тип экземпляра, такой как т2.medium или т2.large, может обеспечить дополнительные ресурсы для обработки больших объемов данных. -
Пересмотр архитектуры:
Если обилие правил перенаправления является постоянной закономерностью, возможно, стоит пересмотреть архитектуру вашей системы. Может быть целесообразным использовать внешние системы управления перенаправлениями или кэшированием, такие как Varnish или Redis, что может уменьшить нагрузку на Nginx. -
Мониторинг и диагностика:
Включите дополнительные инструменты мониторинга, чтобы отслеживать использование памяти и процессоров Nginx. Используйте утилиты, такие какtop
,htop
илиvmstat
, чтобы в реальном времени диагностировать проблемы с памятью.
Заключение
Обработка большого количества правил перенаправления в Nginx может представлять собой сложную задачу, особенно на серверах с ограниченными ресурсами. Применение методов оптимизации, разделение конфигурационных файлов и если возможно – увеличение ресурсов сервера, могут значительно улучшить производительность вашей Nginx конфигурации. В случае возникновения новых проблем, не стесняйтесь обращаться к сообществу или специалистам для получения дополнительной помощи.