NGINX Servindo arquivos mp4 grandes de maneira extremamente ineficiente

8

Atualmente, estou executando o nginx / 1.0.15 em um sistema operacional Centos 6.6. O servidor possui as seguintes especificações:

  • CPU Intel (R) Atom (TM) C2750 a 2,40 GHz (8 núcleos)
  • 32GB Ram
  • 5 x 6000 GB 7200 RPM (Raid 10)

O problema

O servidor tem uma conexão de 1 Gbit / s, no entanto, atinge o ponto mais alto e os gargalos após 400-500 mbit / s. O serviço começa a declinar em aproximadamente 100 conexões .. e a velocidade com o servidor cai drasticamente (apesar de ainda haver 50% da largura de banda disponível)

O servidor NGINX é estritamente para servir arquivos .mp4 estáticos. Cada arquivo geralmente tem 400-1200MB (sendo 700MB a média)

Eu tentei muitas configurações e quase todas elas me deram os mesmos resultados .. Estou extremamente frustrado ..

A carga do servidor também nunca passa de 0,3.

Existe algo flagrantemente errado ou equivocado na minha configuração? Qualquer coisa pode ajudar.

As configurações

/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
fonte
1
Algum motivo específico para estar tão desatualizado? A versão estável agora é 1.8.
poige
@poige eu atualizei nginx para 1,8 estáveis esta manhã
Kennysmoothx
@poige Também notei enquanto olhava para o iotop, a maioria, senão todos os meus processos de trabalho nginx geralmente atingiam 1918 kb / s de leitura. Esse limite de buffer pode ter?
219159 Kennysmoothx
Veja meu perfil para informações de contato.
poige
@Kennysmoothx compartilhar a saída do sysstat e ifstat durante o tempo de streaming de arquivos
Anatoly

Respostas:

5

O melhor começo pode ser o conjunto de regras a seguir:

  1. desativar o log e accept_mutex
  2. ativar sendfile
  3. definir sendfile_max_chunk

Configuração:

events {
    accept_mutex off;
}

access_log off;
sendfile on;
sendfile_max_chunk 512k;

O novo conjunto de encadeamentos de recursos Nginx (1.7.11 ou mais recente) pode ser realmente útil no seu caso:

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

Em amostras de teste, ajuda muito a aumentar a largura de banda de 1 Gbps a 9 Gbps. Nove vezes! Você tem apenas 1 Gbps, mas faz com que tudo seja utilizado.

Veja mais detalhes: https://www.nginx.com/blog/thread-pools-boost-performance-9x/

Anatoly
fonte
Eu tentei isso hoje e infelizmente não há melhorias. Notei que meus processos de trabalho do nginx parecem ter um pico de leitura de 1918kb / s, alguma idéia de qual seja esse limite?
219159 Kennysmoothx
@Kennysmoothx menos provável Nginx porque você tentou quase tudo para configurá-lo para servir arquivos grandes de forma eficiente
Anatoly
@Kennysmoothx isso é antigo, mas você já encontrou uma solução? Eu culparia sua hospedagem, eles podem estar vendendo demais, é por isso que você não alcança 1Gbps. Tente uma hospedagem diferente com a mesma configuração, veja o que você recebe.
Michael Rogers
4

Um bom primeiro lugar para começar é com os arquivos .mp4 reais, onde geralmente há grandes áreas de melhoria.

Portanto, antes de se perder no ajuste do NGINX ou Apache, primeiro ajuste seus arquivos .mp4.

Para este post, o cinema é como um filme ou programa de televisão em que cada mudança de quadro é necessária. Em outras palavras, tentar retranscodificar um filme como "The Croods" para 1 qps (quadro / segundo) reduziria a qualidade a inatingível.

E não cinematográfico refere-se a capturas de tela, como seminários on-line, nossos cursos publicados na Udemy.

Primeiro, considere o componente de áudio do arquivo. Se o componente de áudio estiver falando principalmente, use ffmpeg para transcodificar novamente o arquivo em que você copia o fluxo de vídeo (sem alteração) + converte o fluxo estéreo em mono. Para muitos arquivos .mp4 (não cinematográficos), aproximadamente 1/3 do tamanho do arquivo de filme é vídeo + 1/3 é canal de áudio esquerdo + 1/3 é o canal de áudio direito. Mudar de estéreo para mono pode reduzir consideravelmente o tamanho do arquivo.

Segundo, retranscode o áudio usando o FDK-AAC ( https://github.com/mstorsjo/fdk-aac ), que produz arquivos muito menores do que outros codificadores AAC. A maioria das versões modernas do ffmpeg constrói automaticamente o FDK-AAC atualmente. Até o Macports agora constrói isso. Uma consideração: para o FDK fazer sua mágica real, é necessária uma faixa estéreo + ao usar as compressões de áudio estéreo FDK muito menores que o mono; portanto, se você estiver usando o FDK, use o estéreo.

Terceiro, o áudio reduz a taxa de bits. Muitas vezes, isso é 48k, portanto, em geral, use -ar 44100 (ffmpeg) ou falado (baixa fi) considere cair para 22050.

Quarto, defina a taxa de quadros do seu vídeo o mais baixa possível. Portanto, se você estiver fazendo uma captura de tela, um quadro poderá mudar apenas uma vez em 10 a 60 segundos, para que você possa reduzir a taxa de quadros usando -r $ fps, muitas vezes de 30 a 60 fps a 1-5 fps + a qualidade permanece a mesma enquanto o tamanho do arquivo cai.

Muitas vezes comprimo arquivos não cinematográficos, onde cada 1G reduz para 10-20M.

Quinto, verifique se o faststart mov atom está na frente dos seus arquivos, para que seus arquivos possam ser transmitidos em vez de baixados.

Meus parâmetros ffmpeg fdk ...

-c: um libfdk_aac -profile: a aac_he_v2 -afterburner 1 -sinalização explícita_sbr -vbr 5 -ac 2 -ar 44100

De fato, aqui está um comando ffmpeg completo típico ...

O script mp4 é apenas um invólucro do ffmpeg, que adivinha quais faixas de áudio + vídeo estão em inglês (para arquivos multitrack avi + mkv) + e cria o comando ffmpeg. O que interessa é o comando real, que é o resíduo de anos de experimentos.

Tente executar seus arquivos através da compressão extrema ffmpeg primeiro e verifique se os pesos dos arquivos são tão baixos / pequenos que não há necessidade de ajuste do servidor da Web.

Áreas da experiência: -r $ fps + -v: crf + -v: preset + -ar bitrate

Um pouco de experiência fornecerá as configurações para o menor tamanho de arquivo + qualidade aceitável.

Muitas das opções ímpares, como + genpts + clearing SAR / DAR, estão lá para garantir que os arquivos .mp4 sejam reproduzidos nas unidades Roku. É bom mantê-las, caso você configure seu próprio canal Roku, que é uma maneira gratuita de atingir mais de 5.000.000 de famílias.

Meu 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: um libfdk_aac - perfil: aac_he_v2 -afterburner 1 -signaling explícito-br -vbr 5 -ac 2 -ar 44100 - metadados title = 'Foo (TC)' - roscas 0 -f mp4 -mark 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
fonte
5
Esta resposta não é útil porque o principal problema é servir arquivos grandes de maneira eficiente com o Nginx.
Uncktich
2

A ativação do multi_accept funcionou para mim (o vídeo parava até a metade e o visitante não conseguia ouvir / assistir a outra metade, muito frustrante).

As únicas coisas que defini no nginx.conf nos eventos são as seguintes:

events {
worker_connections 768;
multi_accept on;
}

** Funciona hoje LOL .... amanhã teremos que ver se ainda funciona totalmente

kennyhendrick
fonte