NGINX Sirviendo archivos mp4 grandes extremadamente ineficientemente

8

Actualmente estoy ejecutando nginx / 1.0.15 en un sistema operativo Centos 6.6. El servidor tiene las siguientes especificaciones:

  • Intel (R) Atom (TM) CPU C2750 @ 2.40GHz (8 núcleos)
  • 32 GB de RAM
  • 5 x 6000 GB 7200 RPM (Raid 10)

El problema

El servidor tiene una conexión de 1 Gbit / s, sin embargo, se completa y se cuela después de 400-500 mbit / s. El servicio comienza a disminuir a aproximadamente 100 conexiones ... y la velocidad con el servidor cae drásticamente (a pesar de que todavía hay un 50% de ancho de banda disponible)

El servidor NGINX es estrictamente para servir archivos .mp4 estáticos. Cada archivo suele tener entre 400 y 1200 MB (700 MB como promedio)

He probado muchas configuraciones y casi todas me dan los mismos resultados. Estoy extremadamente frustrado.

La carga del servidor tampoco pasa nunca 0.3.

¿Hay algo descaradamente incorrecto o equivocado en mi configuración? Cualquier cosa puede ayudar.

Las configuraciones

/etc/nginx/nginx.conf

user              nginx;
worker_processes  9;

error_log  /var/log/nginx/error.log;


pid        /var/run/nginx.pid;


events {
    worker_connections  51200;
    use epoll;
 }

worker_rlimit_nofile 600000;

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;
access_log off;

aio on;
sendfile        off;
tcp_nopush      off;
tcp_nodelay      on;

#keepalive_timeout  0;
keepalive_timeout  65;

output_buffers 1 3m;
#gzip  on;

include /etc/nginx/conf.d/*.conf;

open_file_cache          max=10000 inactive=5m;
open_file_cache_valid    2m;
open_file_cache_min_uses 1;
open_file_cache_errors   on;

}

/etc/nginx/conf.d/default.conf

server {
    listen       80 default_server sndbuf=32k;
    server_name  _;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    include /etc/nginx/default.d/*.conf;


    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    location /Videos/ {
        root /home;
        gzip off;
        gzip_static off;

        mp4;
        mp4_max_buffer_size   300m;
    }

    location /stats {
        stub_status on;
    }

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


    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
Kennysmoothx
fuente
1
¿Alguna razón específica para estar tan desactualizado? La versión estable ahora es 1.8.
poige
@poige Actualicé nginx a 1.8 estable esta mañana
Kennysmoothx
@poige También noté mientras miraba a iotop, la mayoría, si no todos, mis procesos de trabajo nginx generalmente estallan hasta 1918 kb / s de lectura. ¿Es ese un límite de búfer que puedo tener?
Kennysmoothx
Vea mi perfil para información de contacto.
poige
@Kennysmoothx comparte la salida de sysstat e ifstat durante el tiempo de transmisión del archivo
Anatoly

Respuestas:

5

El mejor comienzo puede ser el conjunto de reglas siguientes:

  1. deshabilitar el registro y accept_mutex
  2. habilitar sendfile
  3. establecer sendfile_max_chunk

Configuración:

events {
    accept_mutex off;
}

access_log off;
sendfile on;
sendfile_max_chunk 512k;

El nuevo grupo de subprocesos de funciones de Nginx (1.7.11 o más reciente) puede ser realmente útil en su caso:

location / {
    root /home;
    aio threads;
    mp4;
}

En las muestras de prueba, te ayuda dramáticamente a aumentar el ancho de banda de 1 Gbps a 9 Gbps. ¡Nueve veces! Tiene solo 1 Gbps pero lo hace todo utilizado.

Ver más detalles: https://www.nginx.com/blog/thread-pools-boost-performance-9x/

Anatoly
fuente
He intentado esto hoy y desafortunadamente no hay mejoras. Me di cuenta de que mis procesos de trabajo nginx parecen alcanzar un límite de lectura de 1918 kb / s, ¿alguna idea de cuál puede ser ese límite?
Kennysmoothx
@Kennysmoothx es menos probable que sea Nginx porque intentaste casi todo para configurarlo para servir archivos grandes de manera eficiente
Anatoly
@Kennysmoothx esto es antiguo, pero ¿alguna vez encontraste una solución? Culparía a su alojamiento, podrían estar vendiendo demasiado, por eso no alcanza 1Gbps. Pruebe un alojamiento diferente con la misma configuración y vea lo que obtiene.
Michael Rogers
4

Un buen primer lugar para comenzar es con los archivos .mp4 reales, donde generalmente hay áreas masivas de mejora.

Entonces, antes de perderse en el ajuste de NGINX o Apache, primero ajuste sus archivos .mp4.

Para esta publicación cinemática es como una película o un programa de televisión donde se requiere cada cambio de cuadro. En otras palabras, tratar de volver a codificar una película como "The Croods" a 1 fps (cuadro / segundo) reduciría la calidad a imposible de ver.

Y no cinemático se refiere a capturas de pantalla como seminarios web que nuestro curso publicó en Udemy.

Primero, considere el componente de audio del archivo. Si el componente de audio habla principalmente, use ffmpeg para volver a codificar el archivo donde copia la transmisión de video (sin cambios) + convertir la transmisión estéreo a mono. Para muchos archivos .mp4 (no cinemáticos) aproximadamente 1/3 del tamaño del archivo de película es video + 1/3 es el canal de audio izquierdo + 1/3 es el canal de audio derecho. Cambiar de estéreo a mono puede reducir considerablemente el tamaño del archivo.

En segundo lugar, vuelva a codificar el audio con FDK-AAC ( https://github.com/mstorsjo/fdk-aac ) que produce archivos mucho más pequeños que otros codificadores aac. La mayoría de las versiones modernas de ffmpeg automagickally construyen FDK-AAC en estos días. Incluso Macports ahora construye esto. Una consideración, para que FDK haga su verdadera magia requiere una pista estéreo + cuando se usan compresiones de audio estéreo FDK mucho más pequeñas que las mono, por lo que si está usando FDK, quédese con estéreo.

Tercero, para el audio, reduzca la tasa de bits Muchas veces esto es 48k, por lo que, en general, use -ar 44100 (ffmpeg) o para hablado (baja fidelidad) considere caer a 22050.

En cuarto lugar, establezca la velocidad de fotogramas de su video lo más bajo posible. Entonces, si está haciendo una captura de pantalla, un fotograma solo puede cambiar una vez en 10-60 segundos, por lo que puede reducir la velocidad de fotogramas usando -r $ fps, muchas veces de 30-60 fps a 1-5 fps + la calidad sigue siendo la misma mientras que el tamaño del archivo se desploma.

Muchas veces comprimo archivos no cinemáticos donde cada 1G se reduce a 10-20M.

En quinto lugar, asegúrese de que el átomo mov de inicio rápido esté al frente de sus archivos, para que sus archivos se puedan transmitir en lugar de descargar.

Mis parámetros ffmpeg fdk ...

-c: a libfdk_aac -profile: a aac_he_v2 -afterburner 1 -signating explicit_sbr -vbr 5 -ac 2 -ar 44100

De hecho, aquí hay un comando ffmpeg completo típico ...

El script mp4 es solo un contenedor alrededor de ffmpeg que hace cosas como adivinar qué pistas de audio + video están en inglés (para archivos multipista avi + mkv) + luego construye el comando ffmpeg. Lo que interesa es el comando real, que es el residuo de años de experimentos.

Intente ejecutar sus archivos a través de la compresión extrema ffmpeg primero, luego vea si los pesos de los archivos son tan bajos / pequeños que no es necesario ajustar el servidor web.

Áreas de experimento: -r $ fps + -v: crf + -v: preestablecido + -ar bitrate

Un poco de experimentación le dará la configuración para el tamaño de archivo más pequeño + calidad aceptable.

Muchas de las opciones extrañas como + genpts + borrar SAR / DAR están ahí para garantizar que los archivos .mp4 se reproduzcan en unidades Roku. Estos son buenos para mantener, en caso de que configure su propio canal Roku, que es una forma gratuita de llegar a más de 5,000,000 de hogares.

Mi comando ffmpeg ...

imac> mp4 --dr --noisy foo.avi

tc: diag = v:! h264: mpeg4, a:! aac: ac3 title = 'Foo (TC)' Foo-640x480-veryfast-crf18-max-tc.mp4

cd '/Users/david/Downloads/Casper.A.Spirited.Beginning.1997.DVDrip.iNTERNAL.XviD-BPDcarrier' nice -19 ffmpeg -fflags + genpts -i "foo.avi" -map 0: 0 -c: v libx264 -crf: v 18 -preset: v veryfast -tune: v film -level: v 4.1 -profile: v high -bufsize: v 5000k -vf setdar = dar = 0, setsar = sar = 0 -x264opts colorprim = bt709 : transfer = bt709: colormatrix = bt709: fullrange = off -r 29.97 -movflags + faststart -map 0: 1 -c: a libfdk_aac -profile: a aac_he_v2 -afterburner 1 -signaling explicit_sbr -vbr 5 -ac 2 -ar 44100 - metadata title = 'Foo (TC)' -procesos 0 -f mp4 -benchmark Foo-640x480-veryfast-crf18-max-tc.mp4.tmp mv -f Foo-640x480-veryfast-crf18-max-tc.mp4.tmp Foo-640x480-veryfast-crf18-max-tc.mp4

David Favor
fuente
55
Esta respuesta no es útil porque el problema principal es servir archivos grandes de manera eficiente con Nginx.
unwichtich
2

Encender multi_accept funcionó para mí (el video solía detenerse a mitad de camino y el visitante no podía escuchar / mirar la otra mitad, muy frustrante).

Lo único que he configurado en nginx.conf bajo los eventos es esto:

events {
worker_connections 768;
multi_accept on;
}

** Funciona hoy jajaja .... mañana solo tendremos que ver si todavía juega completamente

kennyhendrick
fuente