NGINX servant de gros fichiers mp4 de manière extrêmement inefficace

8

J'utilise actuellement nginx / 1.0.15 sur un système d'exploitation Centos 6.6. Le serveur a les spécifications suivantes:

  • Processeur Intel (R) Atom (TM) C2750 à 2,40 GHz (8 cœurs)
  • 32 Go de RAM
  • 5 x 6000 Go 7200 tr / min (Raid 10)

Le problème

Le serveur dispose d'une connexion à 1 Gbit / s, mais il dépasse et goulots d'étranglement après 400-500 mbit / s. Le service commence à décliner à environ 100 connexions .. et la vitesse avec le serveur chute de façon spectaculaire (malgré 50% de bande passante encore disponible)

Le serveur NGINX est strictement destiné à servir des fichiers .mp4 statiques. Chaque fichier est généralement de 400 à 1200 Mo (700 Mo étant la moyenne)

J'ai essayé de nombreuses configurations et à peu près toutes me donnent les mêmes résultats .. Je suis extrêmement frustré ..

La charge du serveur ne dépasse également jamais 0,3.

Y a-t-il quelque chose de manifestement faux ou erroné dans ma configuration? Tout pourrait aider.

Les configurations

/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
la source
1
Une raison spécifique pour être si dépassée? La version stable est maintenant 1.8.
poige
@poige J'ai mis à jour nginx à 1.8 stable ce matin
Kennysmoothx
@poige J'ai également remarqué en regardant iotop, la plupart sinon la totalité de mes processus de travail nginx explosaient généralement jusqu'à 1918 kb / s en lecture. Est-ce une limite de tampon que je peux avoir?
Kennysmoothx
Voir mon profil pour les coordonnées.
poige
@Kennysmoothx partage la sortie de sysstat et ifstat pendant la durée de diffusion du fichier
Anatoly

Réponses:

5

Le meilleur départ peut être l'ensemble des règles suivantes:

  1. désactiver la journalisation et accept_mutex
  2. activer le fichier d'envoi
  3. définir sendfile_max_chunk

Configuration:

events {
    accept_mutex off;
}

access_log off;
sendfile on;
sendfile_max_chunk 512k;

Le nouveau pool de threads de fonctionnalités Nginx (1.7.11 ou plus récent) peut être très utile dans votre cas:

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

Sur les échantillons de test, il vous aide considérablement à augmenter la bande passante de 1 Gbit / s à 9 Gbit / s. Neuf fois! Vous n'avez que 1 Gbit / s, mais cela permet de tout utiliser.

Voir plus de détails: https://www.nginx.com/blog/thread-pools-boost-performance-9x/

Anatoly
la source
J'ai essayé cela aujourd'hui et malheureusement aucune amélioration .. J'ai remarqué que mes processus de travail nginx semblent dépasser le niveau de lecture à 1918 kb / s, une idée de ce que cette limite peut être?
Kennysmoothx
@Kennysmoothx, il est moins probable que Nginx parce que vous avez essayé presque tout pour le configurer pour servir efficacement les gros fichiers
Anatoly
@Kennysmoothx c'est ancien, mais avez-vous déjà trouvé une solution? Je blâmerais votre hébergement, ils pourraient vendre trop, c'est pourquoi vous n'atteignez pas 1 Gbps. Essayez un hébergement différent avec la même configuration, voyez ce que vous obtenez.
Michael Rogers
4

Un bon premier point de départ est avec les fichiers .mp4 réels, où il y a généralement des améliorations considérables.

Donc, avant de vous perdre dans le réglage de NGINX ou d'Apache, réglez d'abord vos fichiers .mp4.

Pour ce post, la cinématique est comme un film ou une émission de télévision où chaque changement d'image est nécessaire. En d'autres termes, essayer de retranscoder un film comme "The Croods" à 1 fps (image / seconde) réduirait la qualité à inatteignable.

Et non cinématographique fait référence à des captures d'écran comme les webinaires que nos didacticiels ont publiés sur Udemy.

Tout d'abord, considérez le composant audio du fichier. Si le composant audio est principalement parlant, utilisez ffmpeg pour retranscoder le fichier où vous copiez le flux vidéo (sans changement) + convertissez le flux stéréo en mono. Pour de nombreux fichiers .mp4 (non cinématiques), environ 1/3 de la taille du fichier vidéo est vidéo + 1/3 est le canal audio gauche + 1/3 est le canal audio droit. Le passage de stéréo à mono peut réduire considérablement la taille du fichier.

Deuxièmement, retranscode l'audio en utilisant FDK-AAC ( https://github.com/mstorsjo/fdk-aac ) qui produit des fichiers beaucoup plus petits que les autres encodeurs aac. La plupart des versions modernes de ffmpeg construisent automatiquement FDK-AAC de nos jours. Même Macports le construit maintenant. Une considération, pour que FDK fasse sa vraie magie nécessite une piste stéréo + lors de l'utilisation de compressions audio stéréo FDK beaucoup plus petites que mono, donc si vous utilisez FDK, restez avec stéréo.

Troisièmement, pour l'audio, réduisez le débit binaire. Souvent, c'est 48k, donc en général, utilisez -ar 44100 (ffmpeg) ou pour parlé (faible fi), envisagez de passer à 22050.

Ensuite, définissez la fréquence d'images de votre vidéo aussi bas que possible. Donc, si vous faites une capture d'écran, une image ne peut changer qu'une seule fois en 10 à 60 secondes, vous pouvez donc réduire la fréquence d'images à l'aide de -r $ fps, plusieurs fois de 30-60 ips à 1-5 ips + la qualité reste la même tandis que la taille du fichier chute.

Plusieurs fois, je compresse des fichiers non cinématiques où chaque 1G se réduit à 10-20M.

Cinquièmement, assurez-vous que l'atome mov faststart est à l'avant de vos fichiers, afin que vos fichiers puissent être diffusés en continu plutôt que téléchargés.

Mes paramètres ffmpeg fdk ...

-c: un libfdk_aac -profile: un aac_he_v2 -afterburner 1 -signaling explicit_sbr -vbr 5 -ac 2 -ar 44100

En fait, voici une commande ffmpeg complète typique ...

Le script mp4 est juste un wrapper autour de ffmpeg qui fait des choses comme deviner quelles pistes audio + vidéo sont en anglais (pour les fichiers multipiste avi + mkv) + puis construire la commande ffmpeg. Ce qui est intéressant, c'est la commande réelle, qui est le résidu d'années d'expérience.

Essayez d'abord d'exécuter vos fichiers via la compression extrême ffmpeg, puis vérifiez si le poids des fichiers est si faible / faible, aucun réglage de serveur Web n'est requis.

Domaines d'expérimentation: -r $ fps + -v: crf + -v: preset + -ar bitrate

Un peu d'expérimentation vous donnera les paramètres pour la plus petite taille de fichier + une qualité acceptable.

De nombreuses options étranges comme + genpts + effacement SAR / DAR sont là pour assurer la lecture des fichiers .mp4 sur les unités Roku. Celles-ci sont bonnes à conserver, au cas où vous configureriez chacune votre propre chaîne Roku, qui est un moyen gratuit d'atteindre plus de 5 000 000 ménages.

Ma commande 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 - titre de métadonnées = 'Foo (TC)' -fils 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
la source
5
Cette réponse n'est pas utile car le problème principal est de servir efficacement de gros fichiers avec Nginx.
unwichtich
2

L'activation de multi_accept a fonctionné pour moi (la vidéo s'arrêtait à mi-chemin et le visiteur n'a pas pu écouter / regarder l'autre moitié, très frustrant).

Les seules choses que j'ai définies dans nginx.conf sous les événements sont les suivantes:

events {
worker_connections 768;
multi_accept on;
}

** Cela fonctionne aujourd'hui LOL .... demain, nous n'aurons plus qu'à voir s'il continue de jouer pleinement

kennyhendrick
la source