web-dev-qa-db-ja.com

nginxからの大きな静的ファイルのダウンロードが遅い

私はvmware-esxi仮想化でdebian 7 x64を使用しています。

クライアントあたりの最大ダウンロードは1mb/sであり、nginxは一緒に50mbpsを超えて使用しません。私の質問は、転送が遅くなる原因を教えてください。

サーバ

**Settings for eth1:
    Supported ports: [ TP ]
    Supported link modes:   1000baseT/Full
                            10000baseT/Full**

root@www:~# iostat
Linux 3.2.0-4-AMD64 (www)       09.02.2015      _x86_64_        (4 CPU)

avg-cpu:  %user   %Nice %system %iowait  %steal   %idle
       1,75    0,00    0,76    0,64    0,00   96,84

Device:            tps    kB_read/s    kB_wrtn/s    kB_read    kB_wrtn
sda             173,93      1736,11       219,06     354600      44744


root@www:~# free -m
             total       used       free     shared    buffers     cached
Mem:         12048       1047      11000          0        106        442
-/+ buffers/cache:        498      11549
Swap:          713          0        713

nginx.cof

user www-data;
worker_processes 4;
pid /var/run/nginx.pid;

events {
        worker_connections 3072;
        # multi_accept on;
}

http {

        ##
        # Basic Settings
        ##

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 5;
        types_hash_max_size 2048;
        server_tokens off;

        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ##
        # Logging Settings
        ##

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

        ##
        # Gzip Settings
        ##

        gzip on;
        gzip_disable "msie6";

        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

        ##
        # nginx-naxsi config
        ##
        # Uncomment it if you installed nginx-naxsi
        ##

        #include /etc/nginx/naxsi_core.rules;

        ## Start: Size Limits & Buffer Overflows ##

        client_body_buffer_size 1k;
        client_header_buffer_size 1k;
        client_max_body_size 4M;
        large_client_header_buffers 2 1k;

        ## END: Size Limits & Buffer Overflows ##

        ## Start: Timeouts ##

        client_body_timeout   10;
        client_header_timeout 10;
        send_timeout          10;

        ## End: Timeouts ##

        ## END: Size Limits & Buffer Overflof
        ##
        # nginx-passenger config
        ##
        # Uncomment it if you installed nginx-passenger
        ##

        #passenger_root /usr;
        #passenger_Ruby /usr/bin/Ruby;

        ##
        # Virtual Host Configs
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

/etc/sysctl.conf

# Increase system IP port limits to allow for more connections

net.ipv4.ip_local_port_range = 2000 65000


net.ipv4.tcp_window_scaling = 1


# number of packets to keep in backlog before the kernel starts dropping them
net.ipv4.tcp_max_syn_backlog = 3240000


# increase socket listen backlog
net.core.somaxconn = 3240000
net.ipv4.tcp_max_tw_buckets = 1440000


# Increase TCP buffer sizes
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216

更新:

デバッグログが完全に空で、ダウンロードを手動でキャンセルした場合のみ、次のエラーが発生します

2015/02/09 20:05:32 [info] 4452#0: *2786 client prematurely closed connection while sending response to client, client: 83.11.xxx.xxx, server: xxx.com, request: "GET filename HTTP/1.1", Host: "xxx.com"

カール出力:

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 1309M  100 1309M    0     0   374M      0  0:00:03  0:00:03 --:--:--  382M
6

グーグルを通じてここに誰のための答え:

Sendfileはブロックされており、nginxが先読みを設定することを可能にしないため、ファイルが一度だけ読み取られる場合は非常に非効率的です。

Sendfileはファイルシステムキャッシングなどに依存しており、そのような大きなファイル用に作成されたことはありません。

必要なのは、大きなファイルのsendfileを無効にし、代わりにdirectioを使用することです(できればスレッドを使用して非ブロッキングにする)。 16MB未満のファイルは、引き続きsendfileを使用して読み取られます。

aio threads;
directio 16M;
output_buffers 2 1M;

sendfile on;
sendfile_max_chunk 512k;

Directioを使用すると、ディスクから直接読み取り、途中で多くの手順をスキップします。

pS aioスレッドを使用するには、スレッドサポート付きのnginxをコンパイルする必要があることに注意してください https://www.nginx.com/blog/thread-pools-boost-performance-9x/

8
DannyZB

おそらく変更する必要がありますsendfile_max_chunk値、ドキュメントに記載されているとおり:

Syntax:   sendfile_max_chunk size;
Default:  sendfile_max_chunk 0;
Context:  http, server, location

0以外の値に設定すると、1つのsendfile()呼び出しで転送できるデータの量が制限されます。制限がない場合、1つの高速接続でワーカープロセスを完全に占有する可能性があります。

トラフィックのほとんどが「大きな」静的ファイルである場合は、バッファサイズを調整することもできます。

2
Xavier Lucas

チューニングを試しましたか[〜#〜] mtu [〜#〜](最大転送ユニット)-最大のネットワーク層プロトコルデータユニットのサイズ単一のネットワークトランザクションで通信できますか?今回のケースでは、1500バイトから4000バイトに切り替えると、ダウンロードのパフォーマンスが大幅に向上しました。サポートされるMTUは、IPトランスポートによって異なります。ユースケースで意味のあるサイズを評価する別の値を試してください。

ifconfigを使用して既存のMTUサイズを確認し、次のコマンドを使用して実行時にそれを更新できます。

ifconfig eth0 mtu 5000

すべての事柄に関するこの非常に役立つ記事もご覧ください ネットワーク経由で大量のデータを転送する方法

1
VinPro