Nginxのディスクバランシング







この記事では、コンテンツ(ビデオなど)の配信時にディスクシステムがボトルネックになった場合のNginxに基づいた興味深いソリューションについて説明します。



問題の声明



私たちには仕事があります:毎秒数十ギガビットの総配布帯域で静的ファイル(ビデオ)をクライアントに送信する必要があります。



明らかな理由により、このようなバンドはリポジトリから直接配布することはできません;キャッシングを適用する必要があります。 生成されるトラフィックの大部分を占めるコンテンツの量は、1つのサーバーのRAMよりも数桁大きいため、RAMにキャッシュすることはできません。キャッシュはディスクに保存する必要があります。



十分な容量のネットワークチャネルが先験的に利用可能である場合、タスクは解決できません。



ソリューションを選択する



この状況では、ディスクは問題のある場所になります。サーバーが1秒間に20ギガビットのトラフィック(集約で2本の光ファイバー)を生成するには、ディスクから1秒あたり2400メガバイトの有用なデータを読み取る必要があります。 これに加えて、ディスクはキャッシュへの書き込みでビジーになることもあります。

ディスクシステムのパフォーマンスを拡張するには、ブロックを交互に並べたRAIDアレイを使用します。 賭けは、ファイルを読み取るとき、そのブロックは異なるディスク上にあり、ファイルの順次読み取りの速度は平均して、最も遅いディスクの速度に交互のディスクの数を掛けたものに等しくなります。

このアプローチの問題は、断片化せずにファイルシステム内にある十分に長いファイル(ファイルサイズがストリップユニットのサイズよりもはるかに大きい)を読み取る理想的な場合にのみ効果的に機能することです。 多くの小さなファイルや断片化されたファイルの並列読み取りでは、このアプローチではすべてのディスクの合計速度に近づくことさえできません。 たとえば、I / Oキューの負荷が100%の6つのssdディスクのRAID0は、2つのディスクのような速度を提供しました。

個別のファイルシステムを使用して、ディスク全体でファイルを共有する方が収益性が高いことが実践的に示されています。 これにより、すべてのディスクが独立しているため、すべてのディスクがリサイクルされます。



実装



上記のように、nginxをキャッシュします。 アイデアは、ディスク間で分散ファイルを均等に分割することです。 これを行うには、最も簡単な場合、複数のURLのマッピングを複数のドライブにハッシュするだけで十分です。 それが私たちがやることですが、最初に最初のものです。

ディスクの数でキャッシュゾーンを定義します。 私の例では10個あります。

http



セクションで:

  proxy_cache_path /var/www/cache1 levels=1:2 keys_zone=cache1:100m inactive=365d max_size=200g; proxy_cache_path /var/www/cache2 levels=1:2 keys_zone=cache2:100m inactive=365d max_size=200g; ... proxy_cache_path /var/www/cache10 levels=1:2 keys_zone=cache10:100m inactive=365d max_size=200g;
      
      





各キャッシュゾーンのディレクトリに個別のディスクがマウントされます。



コンテンツソースは3つのアップストリームで、各グループに2つのサーバーがあります。

 upstream src1 { server 192.168.1.10; server 192.168.1.11; } upstream src2 { server 192.168.1.12; server 192.168.1.13; } upstream src3 { server 192.168.1.14; server 192.168.1.15; }
      
      





これは、信for性のために取られた、原則外の瞬間です。



server



セクション:



 server { listen 80 default; server_name localhost.localdomain; access_log /var/log/nginx/video.access.log combined buffer=128k; proxy_cache_key $uri; set_by_lua_file $cache_zone /etc/nginx/cache_director.lua 10 $uri_without_args; proxy_cache_min_uses 0; proxy_cache_valid 1y; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404; location ~* ^/site1/.*$ { set $be "src1"; include director; } location ~* ^/site2/.*$ { set $be "src2"; include director; } location ~* ^/site3/.*$ { set $be "src3"; include director; } location @cache1 { bytes on; proxy_temp_path /var/www/cache1/tmp 1 2; proxy_cache cache1; proxy_pass http://$be; } location @cache2 { bytes on; proxy_temp_path /var/www/cache2/tmp 1 2; proxy_cache cache2; proxy_pass http://$be; } ... location @cache10 { bytes on; proxy_temp_path /var/www/cache10/tmp 1 2; proxy_cache cache10; proxy_pass http://$be; } }
      
      





set_by_lua_fileディレクティブは、ハッシュによってこのURLに適切なドライブを選択します。 条件付きの「サイト」の場合、バックエンドが選択されて保存されます。 次に、directorファイルで、内部ロケーションにリダイレクトされます。内部ロケーションは、選択されたバックエンドからのリクエストを処理し、このURLに指定されたキャッシュにレスポンスを保存します。



そして、ここにdirector



ます:

 if ($cache_zone = 0) { return 481; } if ($cache_zone = 1) { return 482; } ... if ($cache_zone = 9) { return 490; } error_page 481 = @cache1; error_page 482 = @cache2; ... error_page 490 = @cache10;
      
      





ひどいように見えますが、これが唯一の方法です。



ハッシュURL->ドライブ、 cache_director.lua



すべての構成ソルト:

 function shards_vector(base, seed) local result = {} local shards = {} for shard_n=0,base-1 do table.insert(shards, shard_n) end for b=base,1,-1 do choosen = math.fmod(seed, b)+1 table.insert(result, shards[choosen]) table.remove(shards, choosen) seed = math.floor(seed / b) end return result end function file_exists(filename) local file = io.open(filename) if file then io.close(file) return 1 else return 0 end end disks = ngx.arg[1] url = ngx.arg[2] sum = 0 for c in url:gmatch"." do sum = sum + string.byte(c) end sh_v = shards_vector(disks, sum) for _, v in pairs(sh_v) do if file_exists("/var/www/cache" .. (tonumber(v)+1) .. "/ready") == 1 then return v end end
      
      





上記のset_by_lua_file



ディレクティブで、このコードはドライブとURLの数を取得します。 少なくとも1つのドライブに障害が発生するまで、URLをドライブに直接マッピングするという考え方は適切です。 問題のあるドライブから正常なURLにリダイレクトするURLは、特定のURLで同じように行う必要があり(そうでない場合はキャッシュヒットはありません)、同時に異なるURLで異なる必要があるため、ロードスキップはありません。 置換置換(など)も失敗した場合、これらのプロパティの両方を保持する必要があります。 したがって、n個のディスクのシステムの場合、URLをこれらのn個のディスクの多くの可能な順列にマップし、次に、配置内のこれらのディスクの順序で、適切なキャッシュを使用しようとします。 ディスク(キャッシュ)アクティビティの基準は、ディレクトリ内にフラグファイルが存在することです。 これらのファイルをチャットして、nginxがそれらを削除しないようにする必要があります。



結果



このようなディスク全体のコンテンツのスミアリングにより、ディスクデバイスの全速度を実際に使用できます。 ワークロードを備えた6つの安価なSSDディスクを備えたサーバーは、ディスクの合計速度に対応する約1200 MB / sのリターンを実現できました。 アレイ速度は約400 MB / sで変動しました



All Articles