Отдача файлов c помощью Nginx

Nginx часто используется только для отдачи файлов. Например, файловый хостинг. На что следует обратить внимание для оптимальной настройки Nginx под отдачу крупных файлов?

Чуть подробнее о характеристиках нашей задачи:

  • Нужно параллельно отдавать много файлов
  • Большинство файлов крупные (более 5 Мб)
  • Мы отдаем потоковое видео и нам необходимо обеспечить комфортный просмотр
  • Мы отдаем звуковые файлы и необходимо обеспечить комфортное прослушивание

Что следует настроить?

sendfile

Как обычно работает Web сервер, при передаче файла:

  1. открывается исходный файл (на диске)
  2. открывается файл назначения (сетевое соединение)
  3. читается блок данных, копируется в буфер и передается по назначению, пока не достигнут конец файла
  4. закрываются оба файла

Это означает, что происходит дополнительное копирование, которое вынужден делать 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Мб

Файлы, которые запрашиваются очень часто имеет смысл кешировать в памяти.

Самое важное

Небольшая настройка Nginx специально для отдачи файлов позволит лучше использовать ресурсы каждого сервера.


Подпишитесь на Хайлоад с помощью Google аккаунта
или закройте эту хрень