Отдача файлов c помощью Nginx
Nginx часто используется только для отдачи файлов. Например, файловый хостинг. На что следует обратить внимание для оптимальной настройки Nginx под отдачу крупных файлов?
Чуть подробнее о характеристиках нашей задачи:
Нужно параллельно отдавать много файлов
Большинство файлов крупные (более 5 Мб)
Мы отдаем потоковое видео и нам необходимо обеспечить комфортный просмотр
Мы отдаем звуковые файлы и необходимо обеспечить комфортное прослушивание
Что следует настроить?
sendfile
Как обычно работает Web сервер, при передаче файла:
открывается исходный файл (на диске)
открывается файл назначения (сетевое соединение)
читается блок данных, копируется в буфер и передается по назначению, пока не достигнут конец файла
закрываются оба файла
Это означает, что происходит дополнительное копирование, которое вынужден делать Web сервер. В этом случае сервер делает системные вызовы read и write. Системный вызов sendfile служит как раз для того, чтобы избежать излишнего копирования и обеспечить прямую передачу файла. Включайте эту опцию (всегда):
sendfile on; tcp_nopush
Директива разрешает или запрещает использовать опции TCP_NOPUSH во FreeBSD или TCP_CORK в Linux. “tcp_nopush on” полезно для sendfile(), nginx в этом случае выводит данные полными пакетами. После того, как весь запрос обработан, TCP_CORK/TCP_NOPUSH выключается, что приводит в сбросу последнего неполного пакета.
tcp_nopush on; tcp_nodelay
Директива разрешает или запрещает использовать опцию TCP_NODELAY (при переходе соединения в состояние keep-alive). Перед переходом соединения в keepalive nginx выводит данные вызовами writev() достаточно большими порциями для заполнения пакета (“postpone_output 1460”), поэтому данные должны уходить без задержек и TCP_NODELAY не нужен. А вот с последним неполным пакетом может случится небольшая задержка, если соединение не закрывается. Для этого и нужно включить TCP_NODELAY:
tcp_nodelay on; directio
Эта опция позволяет включить прямое чтение без обращения в кеш операционной системы. Это полезно для больших файлов, поскольку операционный кеш для них малоэффективен. Опция позволяет задать минимальный размер для включения режима прямого чтения:
directio 10m;
# Файлы более 10Мб Nginx будет читать с диска минуя операционный кеш
expires
Поскольку мы имеем дело со статическими файлами, и есть вероятность того, что один и тот же пользователь сможет несколько раз запросить один и тот же файл, следует включить клиентское кеширование. Это достигается установкой опции “expires max”, которая отправит браузеру нужные заголовки:
expires max; limit_rate
Это достаточно важная опция. Она позволяет ограничить скорость отдачи файлов. В том случае, если Вы отдаете потоковое видео, либо музыку, Вам следует установить ограничения на скорость отдачи. Это позволит сэкономить канал и обслужить больше клиентов:
limit_rate 196K;
# Ограничиваем скорость отдачи до 196Кб/с
Эта опция работает только в рамках одного запроса, а не клиента. Если Вы хотите поставить ограничение на клиента, следует использовать переменную:
set $limit_rate 196K;
В Nginx также есть возможность установить порог отдачи, после которой ограничение войдет в силу. Также имеет смысл для потокового медиа (в этом случае первая указанная часть будет отдаваться без ограничений):
limit_rate_after 1m;
# Ограничение скорости отдачи будет накладываться после 1Мб
Файлы, которые запрашиваются очень часто имеет смысл кешировать в памяти.