Отдача файлов c помощью Nginx
sendfile
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Мб
Файлы, которые запрашиваются очень часто имеет смысл кешировать в памяти.
Самое важное
Небольшая настройка Nginx специально для отдачи файлов позволит лучше использовать ресурсы каждого сервера.