Заход номер два, конфигурационный файл nginx.

Рассмотрим конфиг сервера на примере того что есть у меня под рукой, самый простой веб-сервер, без наворотов и прибамбасов.
Итак разбираем построчно. Небольшое замечание - в примере не указаны значения по умолчанию.

#####################    NGINX.CONF    ###################################

# пользователь от которого запускается сервер
user                    nginx;

# количество потоков, обрабатывающих запросы клиентов, обычно достаточно руководствоваться формулой (количество ядер * 2) + 1 , однако если активно используется диск (или fcgi через unix socket) то имеет смысл добавить ещё несколько процессов, потому что на момент выполнения операций дискового(только ли?) ввода/вывода процесс блокируется, что снижает интерактивность веб-сервера
worker_processes        5;

# ограниечения по количеству открытых файлов (файлом является каталог, файл, сокет) и очереди posix сигналов
worker_rlimit_nofile        10240;
worker_rlimit_sigpending    32768;

# разрешающая способность таймера (влияет на точность времени в логах)
timer_resolution        5000ms;

# приоритет процессов-обработчиков
worker_priority         -5;

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

# Вот что написано в офциальной документации: The directive allows to decrease number gettimeofday() syscalls. By default gettimeofday() is called after each return from kevent(), epoll, /dev/poll, select(), poll(). But if you need an exact time in logs when logging $upstream_response_time, or $msec variables, then you should use timer_resolution. То есть эта директива позволяет уменьшить количество системных вызовов gettimeofday(), что бывает полезно при больших нагрузках однако при этом падает точность временных отметок в логах. По-умолчанию вызов gettimeofday() производится при выходе из kevent(), epoll, /dev/poll, select(), poll().

error_log         /var/log/nginx/error.log;
#error_log        /var/log/nginx/error.log  notice;
#error_log        /var/log/nginx/error.log  info;
pid               /var/run/nginx.pid;

events {
# количество соединений, обрабатываемых каждым потоком
    worker_connections  1024;

# механизм переключения между потоками, у нас нормальная система, поэтому мы используем epoll, а не kqueue и не ту муть которую нам предлагает венда
    use         epoll;

# используется ли мьютекс для вызова accept(), если нет, тогда используется лок-файл (путь к которому задаётся директивой lock_file /путь/к/файлу; ), что значительно медленнее
    accept_mutex    on;

# Если рабочий процесс не имеет ассоциированного с ним мьютекса с системным вызовом accept(), то по просшествии этого времени он будет снова пытаться найти этот мьютекс. Иными словами частота опроса сокета на предмет приёма очередного коннекта
    accept_mutex_delay  10000ms;
# следует отметить, что при больших нагрузках точность таймера начинает плавать, а при огромных (более 20 на одноядерном процессоре по показаниям top) весьма заметно, кроме того разрешающая способность ванильного ядра довольно высока - единицы милисекунд, а у RT ядра 1 милисекунда.

# несколько запросов на мьютекс
    multi_accept    on;
}

http {

    include       /etc/nginx/mime.types;

    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] $request '
                      '"$status" $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log      /var/log/nginx/access.log  main;

# формально корень сайта (очень желательно, чтобы совпадал с тем, который задаётся в момент сборки сервера, но необязательно)
    root /var/www;

# подписывать ли версию ПО сервера в ответе клиенту
    server_tokens   on;

# без коментариев
    ignore_invalid_headers              on;

#
    server_name_in_redirect             off;

# таблица соответствий имени виртуального хоста его адресу
    server_names_hash_bucket_size       128;

# ограничение по скорости на интерфейсах в том числе и backend и fcgi(?)
    limit_rate                          10000M;

# наверно идеальным можно считать буфер, равный средне арифметической длине отдаваемых наиболее часто страниц...
    output_buffers                      256      96k;

# системный вызов, если реализован в операционном окружении, его использование ускоряет отдачу контента небольшой и средней величины, если отдаваемые файлы слишком большие и их количество велико sendfile начинает уходить в своп, а это уже плохо
    sendfile                            on;

# размер разового куска информации для системного вызова sendfile
    sendfile_max_chunk                  128k;

# использовать ли при создании сокета опцию TCP_NOPUSH на FreeBSD или TCP_CORK на Linux
#"tcp_nopush on" полезно для sendfile(), он в этом случае выводит данные полными пакетами. После того, как весь запрос обработан, TCP_CORK/TCP_NOPUSH выключается, что приводит в сбросу последнего неполного пакета.
    tcp_nopush                          on;

# использовать ли при создании сокета опцию TCP_NODELAY, применяется только к keepalive соединениям (вроде бы отключает алгоритм nagle, при котором сразу после инициализации берётся маленькая пауза, после которой начинается передача данных)
    tcp_nodelay                         on;
#
    postpone_output                     1460;
#"tcp_nodelay on" полезно для keep-alive. nginx включает TCP_NODELAY только по окончании запроса, после которого соединение переходит в состоянии keep-alive. До этого nginx выводит данные вызовами writev() достаточно большими порциями для заполнения пакета ("postpone_output 1460"), поэтому данные должны уходить без задержек и TCP_NODELAY не нужен. А вот с последним неполным пакетом может случится небольшая задержка, если соединение не закрывается. Для этого и нужно включить TCP_NODELAY.

# как долго держать соединение открытым в надежде получить данные по нему (очередной http запрос)
    keepalive_timeout                   30;

# посылать rst пакет, по истечении таймаута соединения
    reset_timedout_connection           on;

# считать соединение разорванным по истечении этого времени в секундах
    send_timeout                        90;

# linger connection - полузакрытое соединение, возникает при http pipelining, а также при запросах PUT и POST, если авторизация не была произведена корректно. Это соединения в состоянии FIN_WAIT_2 в rfc ничего не сказано по поводу таймаута такого соединения, то есть формально это соединение должно болтаться до перезагрузки системы, однако большинство операционных систем научились бороться с этим явлением выставляя таким соединениям таймауты, и тем самым сознательно идя на нарушение rfc протокола tcp, однако принято считать, что это вынужденное нарушение из-за несовершенства описания этой ситуации.
#
    lingering_time                      90;

#
    lingering_timeout                   90;

# количество захэшированных mime-типов данных
    types_hash_bucket_size      128;

# Разрешает или запрещает выдавать в ответе строку заголовка "Vary: Accept-Encoding", если директивы gzip или gzip_static активны.
    gzip_vary           on;

# выключить сжатие для "кривых" браузеров
    gzip_disable "MSIE [1-6]\.";

# включить сжатие исходящего контента глобально
    gzip on;

# Директива задаёт число и размер буферов, в которые будет сжиматься ответ. По умолчанию размер одного буфера равен размеру страницы памяти, в зависимости от платформы это или 4K (x86), или 8K. До версии 0.7.28 по умолчанию использовалось 4 буфера размером 4K или 8K.
    gzip_buffers 40 8k;

# наибыстрейшее сжатие при наименьшей загрузке процессора
    gzip_comp_level 1;

# сжимать проксированные запросы
    gzip_proxied any;

# типы контента, которые сжимать
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss;

# используется для чтения тела ответа. В том числе и для записи в файл.
    client_body_buffer_size 32k;

# Кэш дескрипторов файлов, названия красноречивы
    open_file_cache          max=1000  inactive=20m;
    open_file_cache_valid    30m;
    open_file_cache_min_uses 2;
    open_file_cache_errors   on;

    proxy_cache_path  /tmp/nginx-cache  levels=1:2   keys_zone=one:10m inactive=20m max_size=500m;

    # Load config files from the /etc/nginx/conf.d directory
    include /etc/nginx/conf.d/*.conf;

    #
    # The default server
    #
    server {
# Для гигабитной сети вполне подойдут эти настройки, бэклог в операционном окружении должен быть больше чем обозначенный здесь
        listen       80 default backlog=4096 rcvbuf=2777216 sndbuf=2777216 deferred;
        server_name  10.32.0.232;
# опциональная настройка - где находится DNS сервер - очень хороший вариант повесить его на ту же тачку в качестве dns прокса и настроить его на проксирование запросов к нескольким внешним dns (желательно не менее чем к трём, если на сайт приходит довольно много народу, более 100 человек одновременно, желательно повесить это на отдельную сетевушку, которая работает для backend сети)
        resolver     127.0.0.1;
        resolver_timeout 3s;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;
        root /var/www;
        location / {
            root   /var/www/html;
            index  index.html;
        }
    location /distr {
        root /var/www;
        autoindex on;
    }
    location /mrepo {
        root /var/www;
        ssi on;
        ssi_types text/shtml;
        autoindex on;
    }
    location /icons {
        root /var/www;
    }
    location /usage {
        root /var/www;
    }

        error_page  404              /404.html;
        location = /404.html {
            root   /usr/share/nginx/html;
        }

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }

        # proxy the PHP scripts to Apache listening on 127.0.0.1:80
        #
        #location ~ \.php$ {
        #    proxy_pass   http://127.0.0.1;
        #}

# запросы к перловым скриптам - на бэкэнд
        location ~ \.pl$ {
# если файла нет, незачем тратить на него ресурсы бэкэнда
                    if (!-f $request_filename) {
                        return 404;
                        break;
                    }
                    proxy_pass                      http://127.0.0.1:8000;
                    proxy_redirect                  off;
                    proxy_set_header                Host            $host;
                    proxy_set_header                X-Real-IP       $remote_addr;
                    proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;
                    client_max_body_size            10m;
                    client_body_buffer_size         512k;
                    proxy_buffering                 on;
                    output_buffers                  4096           8k;
                    proxy_connect_timeout           40;
                    proxy_send_timeout              40;
                    proxy_read_timeout              90;
                    proxy_buffer_size               8k; # < - если маленький, может быть причиной нерегулярных 500-х ошибок, подбирается с небольшим запасом, большой буфер вызывает задержки
                    proxy_buffers                   32              16k;
                    proxy_busy_buffers_size         64k;
                    proxy_temp_file_write_size      256k;
# относительно свежая фича - кэширование ответа от апстрима - следует использовать довольно осторожно, на некоторых приложениях может вызывать ошибки или непредвиденную реакцию, например у squirrel mail если неправильно авторизуешься, то потом долго не получится авторизоваться :)
                    proxy_cache_key "$scheme://$host$uri$is_args$args:";
# используем хранилище под названием one, описанное выше в proxy_cache_path
                    proxy_cache one;
                    proxy_cache_min_uses 1;
                    proxy_cache_valid 200 30s;
                    proxy_cache_use_stale error timeout http_500 http_502 http_503;
        }

        # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        #

        location ~ \.php$ {
# если файла нет, незачем тратить на него ресурсы fcgi
            if (-f $request_filename) {
                return 404;
                break;
            }
            root           /var/www/cgi-bin;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www/cgi-bin$fastcgi_script_name;
            include        fastcgi_params;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        location ~ /\.ht {
            deny  all;
        }
    }
}

Форматирование немного съехало из-за использования тэга <PRE>

Next Post