Info
Content

Введение


Сигналы

~$ nginx -s SIGNAL запущенным nginx'ом можно управлять с помощью сигналов

  • stop - быстрое завершение
  • quit - плавное завершение (с ожиданием завершения текущих запросов)
  • reload - перечитывание конф. файла
  • reopen - переоткрытие лог-файлов

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

Алгоритм обработки сигнала на перечитывание конф. файла (reload):

  • проверить синтаксис нового конф. файла и попытаться его применить
  1. запустить новые рабочие процессы (с новым конфигом) и новые соединения отдавать им
  2. завершить старые рабочие процессы:
    • запретить им не принимать новые запросы и дообслуживать уже принятые
    • когда старый процесс обслужил все старые соединения он завершается

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

Посылать сигналы можно также и с помощью ~$ kill -s SIGNAL PID (через kill можно отправить сигнал конкретному процессу)

PID главного процесса находится в файле nginx.pid в /usr/local/nginx/logs или /var/run. Изменить имя этого файла можно при конфигурации сборки или же в nginx.conf директивой pid как в примере ниже:

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
...

Сигналы для главного процесса:

  • TERM,INT - быстрое завершение
  • QUIT - плавное завершение
  • HUP - изменение конфигурации, обновление изменившейся временной зоны, запуск новых рабочих процессов с новой конфигурацией, плавное завершение старых рабочих процессов
  • USR1 - переоткрытие лог-файлов
  • USR2 - обновление исполняемого файла
  • WINCH - плавное завершение рабочих процессов

Сигналы для рабочих процессов (ими управлять не нужно, но можно):

  • TERM,INT - быстрое завершение
  • QUIT - плавное завершение
  • USR1 - переоткрытие лог-файлов
  • WINCH - аварийное завершение для отладки

Директивы

nginx состоит из модулей, которые настраиваются директивами в nginx.conf

  • простые - NAME VALUE; имя и значение через пробел
  • блочные - NAME VALUE {DIRECTIVES OR INSTRUCTIONS}
    • если внутри директивы можно указать другие директивы, то она называется контекст (events, http, server, location)

Директивы, помещённые в конфигурационном файле вне любого контекста, считаются находящимися в контексте main. Директивы events и http располагаются в контексте main, server — в http, а location — в server

Комментарии пишутся через решетку

# комментарий

Статический контент

Одна из важных задач nginx - раздача статических файлов

Например:

  • /data/www - html-файлы
  • /data/images - изображения

Нужно настроить блок server с двумя блоками location внутри блока html.

http {
  server {
    location / {
      root /usr/share/nginx/html/data/www;
    }
    location /images/ {
      root /usr/share/nginx/html/data/images;
    }
  }
}

Директива root в блоке server используется, когда в директиве location не указан собственный root

server {
    listen 8080;
    root /data/up1;

    location / {
    }
}

Если есть совпадение с несколькими блоками location, nginx выбирает блок с самым длинным префиксом


Простой прокси-сервер

Конфиг проксируемого сервера, который будет раздавать все кроме изображений:

server {
  listen 88;
  root /usr/share/nginx/html/data/up1;
}

Конфиг прокси-сервера, который раздает изображения (которые запрашиваются из корня сайта) и проксирует остальные запросы к прокси-серверу:

server {
  location / {
    proxy_pass http://localhost:88;
  }
  location ~ \.(gif|jpg|png)$ {
    root /usr/share/nginx/html/data/images;
  }
}

Nginx можно использовать для перенаправления запросов на FastCGI серверы. Базовая конфигурация nginx для работы с проксируемым FastCGI-сервером включает в себя использование директивы fastcgi_pass вместо директивы proxy_pass, и директив fastcgi_param для настройки параметров, передаваемых FastCGI-серверу

Пример:

server {
    location / {
        fastcgi_pass  localhost:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
    }

    location ~ \.(gif|jpg|png)$ {
        root /data/images;
    }
}

Изменение конфигурации

После изменения конфига и попытки применить его, например сигналом HUP, происходит следующее:

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

Мастер-процесс и его рабочие

PID  PPID USER      %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
33127 33126 nobody   0.0  1380 kqread nginx: worker process (nginx)
33128 33126 nobody   0.0  1364 kqread nginx: worker process (nginx)
33129 33126 nobody   0.0  1364 kqread nginx: worker process (nginx)

Применяем конфиг с изменениями (процесс 33129 со старым конфигом дообслуживает свои соединения и не берет новые, обслужив их он завершается)

 PID  PPID USER     %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
33129 33126 nobody   0.0  1380 kqread nginx: worker process is shutting down (nginx)
33134 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33135 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33136 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)

Остались только рабочие с новым конфигом

PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
33134 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33135 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)
33136 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)

Ротация лог-файлов

  • Лог-файлы нужно переименовать (например из access.log в access.log.0)
  • Затем послать сигнал USR1 главному процессу (kill -USR1 `cat ~nginx.pid` либо как-то иначе):
    • Он откроет заново все текущие открытые файлы и назначит им в качестве владельца непривилегированного пользователя, под которым работают рабочие процессы
    • После успешного открытия главный процесс закрывает все открытые файлы и посылает сообщение о переоткрытии файлов рабочим процессам. Они также открывают новые файлы и сразу же закрывают старые
      В результате старые файлы практически сразу же готовы для дальнейшей обработки, например, их можно сжимать

Обновление

Для обновления исполняемого файла сервера вначале нужно записать на место старого файла новый. Затем нужно послать сигнал USR2 главному процессу — он переименует свой файл с номером процесса в файл с суффиксом .oldbin, например, /usr/local/nginx/logs/nginx.pid.oldbin, после чего запустит новый исполняемый файл, а тот в свою очередь — свои рабочие процессы:

    PID  PPID USER    %CPU   VSZ WCHAN  COMMAND  
    33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx  
    33134 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)  
    33135 33126 nobody   0.0  1380 kqread nginx: worker process (nginx)  
    33136 33126 nobody   0.0  1368 kqread nginx: worker process (nginx)  
    36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx  
    36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)  
    36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)  
    36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

Теперь все рабочие процессы наравне принимают запросы. Если послать сигнал WINCH первому главному процессу, то он пошлёт своим рабочим процессам сообщение о плавном выходе, и они будут постепенно выходить:

      PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
    33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
    33135 33126 nobody   0.0  1380 kqread nginx: worker process is shutting down (nginx)
    36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
    36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

По истечении времени запросы будут обрабатывать только новые рабочие процессы:

      PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
    33126     1 root     0.0  1164 pause  nginx: master process /usr/local/nginx/sbin/nginx
    36264 33126 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
    36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

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

  • Послать старому главному процессу сигнал HUP. Старый главный процесс, не перечитывая конфигурации, запустит новые рабочие процессы. После этого можно плавно завершить все новые процессы, послав новому главному процессу сигнал QUIT

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

Если новый главный процесс выходит, то старый главный процесс убирает суффикс .oldbin из имени файла с номером процесса.

Если же обновление прошло удачно, то старому процессу нужно послать сигнал QUIT, и останутся только новые процессы:

      PID  PPID USER    %CPU   VSZ WCHAN  COMMAND
    36264     1 root     0.0  1148 pause  nginx: master process /usr/local/nginx/sbin/nginx
    36265 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36266 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)
    36267 36264 nobody   0.0  1364 kqread nginx: worker process (nginx)

Обработка соединений

С помощью директивы use можно явно указать метод обработки соединений.
Поддерживаются следующие методы обработки соединений:

  • select — стандартный метод. Модуль для поддержки этого метода собирается автоматически, если на платформе не обнаружено более эффективного метода
    Можно принудительно разрешить или запретить сборку этого модуля с помощью параметров --with-select_module и --without-select_module

  • poll — стандартный метод. Модуль для поддержки этого метода собирается автоматически, если на платформе не обнаружено более эффективного метода. Можно принудительно разрешить или запретить сборку этого модуля с помощью параметров --with-poll_module и --without-poll_module

  • kqueue — эффективный метод, используемый во FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 и macOS

  • epoll — эффективный метод, используемый в Linux 2.6+

Чтобы решить, какому серверу отдать на обработку запрос, nginx сравнивает директивы server_name серверов с полем Host в заголовке запроса, и если нет совпадений, то запрос отдается серверу по умолчанию.

server {
    listen      80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      80;
    server_name example.com www.example.com;
    ...
}

Сервер по умолчанию можно задать явно с помощью параметра default_server в директиве listen (это свойство слушающего порта, а не имени сервера):

server {
  listen 80 default_server;
  server_name example.net www.example.net;
  ...
}

Если запросы без поля “Host” в заголовке не должны обрабатываться, можно определить сервер, который будет их отклонять:

server {
  listen 80;
  server_name ""; # имя сервера = пустая строка
  return 444; # спец код ответа, создан спец для nginx
}

Обработка запроса по имени сервера и ip
Серверы слушают на разных адресах:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:80;
    server_name example.com www.example.com;
    ...
}

В таком случае, чтобы выбрать сервер для обработки запроса, сначала будет сравниваться адрес и порт, а уже потом имя сервера, если на подходящих по адресу и порту серверах не будет найдено подходящее имя то запрос будет передан серверу по умолчанию (ведь сервер по умолчанию это свойство порта, а не имени)

У разных портов свои серверы по умолчанию. Пример:

server {
    listen      192.168.1.1:80;
    server_name example.org www.example.org;
    ...
}
server {
    listen      192.168.1.1:80 default_server;
    server_name example.net www.example.net;
    ...
}
server {
    listen      192.168.1.2:8080 default_server;
    server_name example.com www.example.com;
    ...
}

Конфигурация простого сайта PHP


Имя сервера

Имя сервера задается директивой server_name, по нему в том числе определяется в каком сервере будет обработано соединение. Имя может задаваться с помощью маски или регулярного выражения. Если запросу соответствует несколько имен, то сервер будет выбран в соответствии с следующим приоритетом:

  1. точное имя
  2. самое длинное имя с маской в начале, например “*.example.org”
  3. самое длинное имя с маской в конце, например “mail.*”
  4. первое подходящее регулярное выражение (в порядке следования в конфигурационном файле)

Имена с масками

Имя с маской может содержать звёздочку (“”) только в начале или в конце имени, и только на границе, определяемой точкой. Имена “www..example.org” и “w*.example.org” являются некорректными, но их можно задать с помощью регулярных выражений, например, “~^www..+.example.org$” и “~^w..example.org$”. Звёздочка может соответствовать нескольким частям имени. Имени с маской “.example.org” соответствует не только www.example.org, но и www.sub.example.org.

Специальное имя с маской вида “.example.org” соответствует как точному имени “example.org”, так и маске “*.example.org”.

Имена, заданные регулярными выражениями
Регулярное выражение начинается с тильды ~, если тильды нет, то нет и регулярного выражения.
Начало и конец строки обозначаются следующими символами:

  • ^ начало
  • $ конец

К именованному выделению в регулярном выражении можно впоследствии обратиться через переменную:

server {
    server_name   ~^(www\.)?(?<domain>.+)$;
    location / {
        root   /sites/$domain;
    }
}

Обозначить переменную можно так (первые два варианта более новые, если возникает ошибка можно попробовать третий (более старый) варинт):

  • ?<name>
  • ?'name'
  • ?P<name>

Специальные имена
Если нужно обрабатывать запросы без заголовка Host, то нужно добавить в server_name пустую строку ""
Также в server_name можно указать ip-адрес, потому что он иногда бывает в заголовке Host

Интернационализованные доменные имена
Их надо переводить в punycode.


Логи

Для работы отладочного лога nginx должен быть сконфигурирован с поддержкой отладки на этапе сборки ./configure --with-debug ...

В директиве error_log указывается уровень debug error_log /path/to/log debug;

Переопределение лога без одновременного указания уровня debug отключит отладочный лог
В примере ниже, переопределение лога на уровне server отключает отладочный лог для этого сервера:

error_log /path/to/log debug;
http {
  server {
    error_log /path/to/log;
      ...

Можно включить отладочный лог только для определённых клиентских адресов:

error_log /path/to/log;
events {
    debug_connection 192.168.1.1;
    debug_connection 192.168.10.0/24;
}

Можно отправлять логи сразу в syslog. Настраивается с помощью следующих директив:

  • server=адрес Задаёт адрес сервера syslog. Адрес может быть указан в виде доменного имени или IP-адреса, и необязательного порта, или в виде пути UNIX-сокета, который указывается после префикса “unix:”. Если порт не указан, используется UDP-порт 514. Если доменному имени соответствует несколько IP-адресов, используется только первый адрес
  • facility=строка Задаёт категорию сообщений syslog в соответствии с RFC 3164. В качестве категории может быть указано одно из следующих значений:
    • kern
    • user
    • mail
    • daemon
    • auth
    • intern
    • lpr
    • news
    • uucp
    • clock
    • authpriv
    • ftp
    • ntp
    • audit
    • alert
    • cron
    • local0 .. local7 По умолчанию используется “local7”.
  • severity=строка Задаёт важность сообщений syslog для access_log в соответствии с RFC 3164. Возможны те же самые значения, что и у второго параметра (уровень) директивы error_log. По умолчанию используется info.

Важность сообщений об ошибках определяется самим nginx, поэтому в директиве error_log параметр игнорируется.

  • tag=строка Задаёт метку сообщений syslog. По умолчанию используется nginx.
  • nohostname Запрещает добавление поля hostname в заголовок сообщения syslog (1.9.7).

Пример конфигурации syslog:

error_log syslog:server=192.168.1.1 debug;
access_log syslog:server=unix:/var/log/nginx.sock,nohostname;
access_log syslog:server=[2001:db8::1]:12345,facility=local7,tag=nginx,severity=info combined;

Единицы измерения

  • По умолчанию байты
  • k|K Килобайты
  • m|M Мегабайты
  • ms миллисекунды
  • s секунды (по умолчанию)
  • m минуты
  • h часы
  • d дни
  • w недели
  • M месяцы, 30 дней
  • y годы, 365 дней

Их можно комбинировать, указывая от более к менее значащим через пробел, например: 4d 13h


Параметры в командной строке

  • -?|-h Справка
  • -c FILE Использовать альтернативный конфиг вместо дефолтного
  • -g DIRECTIVES Указать глобальные директивы (прям как в конфиг файле только в строку)
  • -p PREFIX Префикс пути до директории с nginx (по дефолту /usr/local/nginx)
  • -q Вывод только ошибок при тестировании конфигурации
  • -s SIGNAL Сигнал главному процессу (stop,quit,reload,reopen)
  • -t Тестирование нового конфига
  • -T То же что и -t только с выводом конфигов в stdout
  • -v Версия
  • -V Подробная версия


Оптимизация

http://nginx.org/ru/docs/http/server_names.html#optimization


HTTPS

Минимум для работы ssl:

server {
    listen              443 ssl;
    server_name         example.com;
    ssl_certificate     example.com.crt;
    ssl_certificate_key example.com.key;
    ...
}

Сертификат - публичный
Ключ - приватный (нужно ограничивать права, но так чтобы главный процесс мог прочитать)

По умолчанию nginx использует ssl_protocols TLSv1 TLSv1.1 TLSv1.2 и ssl_ciphers HIGH:!aNULL:!MD5, поэтому их явная настройка в общем случае не требуется

SSL-сессии хранятся в кэше, который разделяют между собой рабочие процессы (настраивается директивой sss_session_cache)

В файл с цепочкой сертификатов нужно сначала записать сертификат, а потом цепочку (bundle)(если нарушен порядок, то будет ошибка как на скрине ниже) и указать этот файл вместо сертификата в директиве ssl_certificate

Screenshot-from-2019-07-08-18-59-22.png

В случае ниже на любой запрос будет отдан сертификат от www.example.com (потому что ssl-соединение создается раньше чем http в котором передается заголовок Host)

server {
    listen          192.168.1.1:443 ssl;
    server_name     www.example.com;
    ssl_certificate www.example.com.crt;
    ...
}
server {
    listen          192.168.1.2:443 ssl;
    server_name     www.example.org;
    ssl_certificate www.example.org.crt;
    ...
}

Лучше поместить сведения о файле сертификата с несколькими именами и файле с его секретным ключом на уровне конфигурации http, чтобы все серверы унаследовали их единственную копию в памяти

ssl_certificate     common.crt;
ssl_certificate_key common.key;
server {
    listen          443 ssl;
    server_name     www.example.com;
    ...
}
server {
    listen          443 ssl;
    server_name     www.example.org;
    ...
}

No Comments
Back to top