NFS v3とv4


11

NFS v4がNFS v3よりもはるかに高速になる理由と、v3に調整可能なパラメーターがあるかどうかは疑問です。

ファイルシステムをマウントします

sudo mount  -o  'rw,bg,hard,nointr,rsize=1048576,wsize=1048576,vers=4'  toto:/test /test

そして実行する

 dd if=/test/file  of=/dev/null bs=1024k

私は読むことができます200〜400メガバイト/秒 が、ときに私の変更バージョンにvers=3再マウント、と私は取得のみddを再実行して90メガバイト/秒。読み取り中のファイルは、NFSサーバー上のメモリ内ファイルです。接続の両側はSolarisであり、10GbE NICを備えています。すべてのテスト間で再マウントすることにより、クライアント側のキャッシュを回避します。私が使用dtraceNFS経由で提供されているどれだけ速くデータを測定するために、サーバー上で参照すること。v3とv4の両方について、次のように変更しました。

 nfs4_bsize
 nfs3_bsize

デフォルトの32Kから1M(v4では32Kで最大150MB / s)を調整しようとしました

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_clusters

v3のパフォーマンスを改善しますが、行きません。

v3で4つのパラレルを実行するとdd、スループットが90MB / sから70-80MBに低下するため、問題は共有リソースであると思われます。資源。

ウィンドウサイズを取得するdtraceコード:

#!/usr/sbin/dtrace -s
#pragma D option quiet
#pragma D option defaultargs

inline string ADDR=$$1;

dtrace:::BEGIN
{
       TITLE = 10;
       title = 0;
       printf("starting up ...\n");
       self->start = 0;
}

tcp:::send, tcp:::receive
/   self->start == 0  /
{
     walltime[args[1]->cs_cid]= timestamp;
     self->start = 1;
}

tcp:::send, tcp:::receive
/   title == 0  &&
     ( ADDR == NULL || args[3]->tcps_raddr == ADDR  ) /
{
      printf("%4s %15s %6s %6s %6s %8s %8s %8s %8s %8s  %8s %8s %8s  %8s %8s\n",
        "cid",
        "ip",
        "usend"    ,
        "urecd" ,
        "delta"  ,
        "send"  ,
        "recd"  ,
        "ssz"  ,
        "sscal"  ,
        "rsz",
        "rscal",
        "congw",
        "conthr",
        "flags",
        "retran"
      );
      title = TITLE ;
}

tcp:::send
/     ( ADDR == NULL || args[3]->tcps_raddr == ADDR ) /
{
    nfs[args[1]->cs_cid]=1; /* this is an NFS thread */
    this->delta= timestamp-walltime[args[1]->cs_cid];
    walltime[args[1]->cs_cid]=timestamp;
    this->flags="";
    this->flags= strjoin((( args[4]->tcp_flags & TH_FIN ) ? "FIN|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_SYN ) ? "SYN|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_RST ) ? "RST|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_PUSH ) ? "PUSH|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_ACK ) ? "ACK|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_URG ) ? "URG|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_ECE ) ? "ECE|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_CWR ) ? "CWR|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags == 0 ) ? "null " : ""),this->flags);
    printf("%5d %14s %6d %6d %6d %8d \ %-8s %8d %6d %8d  %8d %8d %12d %s %d  \n",
        args[1]->cs_cid%1000,
        args[3]->tcps_raddr  ,
        args[3]->tcps_snxt - args[3]->tcps_suna ,
        args[3]->tcps_rnxt - args[3]->tcps_rack,
        this->delta/1000,
        args[2]->ip_plength - args[4]->tcp_offset,
        "",
        args[3]->tcps_swnd,
        args[3]->tcps_snd_ws,
        args[3]->tcps_rwnd,
        args[3]->tcps_rcv_ws,
        args[3]->tcps_cwnd,
        args[3]->tcps_cwnd_ssthresh,
        this->flags,
        args[3]->tcps_retransmit
      );
    this->flags=0;
    title--;
    this->delta=0;
}

tcp:::receive
/ nfs[args[1]->cs_cid] &&  ( ADDR == NULL || args[3]->tcps_raddr == ADDR ) /
{
    this->delta= timestamp-walltime[args[1]->cs_cid];
    walltime[args[1]->cs_cid]=timestamp;
    this->flags="";
    this->flags= strjoin((( args[4]->tcp_flags & TH_FIN ) ? "FIN|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_SYN ) ? "SYN|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_RST ) ? "RST|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_PUSH ) ? "PUSH|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_ACK ) ? "ACK|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_URG ) ? "URG|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_ECE ) ? "ECE|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags & TH_CWR ) ? "CWR|" : ""),this->flags);
    this->flags= strjoin((( args[4]->tcp_flags == 0 ) ? "null " : ""),this->flags);
    printf("%5d %14s %6d %6d %6d %8s / %-8d %8d %6d %8d  %8d %8d %12d %s %d  \n",
        args[1]->cs_cid%1000,
        args[3]->tcps_raddr  ,
        args[3]->tcps_snxt - args[3]->tcps_suna ,
        args[3]->tcps_rnxt - args[3]->tcps_rack,
        this->delta/1000,
        "",
        args[2]->ip_plength - args[4]->tcp_offset,
        args[3]->tcps_swnd,
        args[3]->tcps_snd_ws,
        args[3]->tcps_rwnd,
        args[3]->tcps_rcv_ws,
        args[3]->tcps_cwnd,
        args[3]->tcps_cwnd_ssthresh,
        this->flags,
        args[3]->tcps_retransmit
      );
    this->flags=0;
    title--;
    this->delta=0;
}

出力は次のようになります(この特定の状況からではありません):

cid              ip  usend  urecd  delta     send     recd      ssz    sscal      rsz     rscal    congw   conthr     flags   retran
  320 192.168.100.186    240      0    272      240 \             49232      0  1049800         5  1049800         2896 ACK|PUSH| 0
  320 192.168.100.186    240      0    196          / 68          49232      0  1049800         5  1049800         2896 ACK|PUSH| 0
  320 192.168.100.186      0      0  27445        0 \             49232      0  1049800         5  1049800         2896 ACK| 0
   24 192.168.100.177      0      0 255562          / 52          64060      0    64240         0    91980         2920 ACK|PUSH| 0
   24 192.168.100.177     52      0    301       52 \             64060      0    64240         0    91980         2920 ACK|PUSH| 0

いくつかのヘッダー

usend - unacknowledged send bytes
urecd - unacknowledged received bytes
ssz - send window
rsz - receive window
congw - congestion window

v3とv4でddのスヌープを取得して比較することを計画しています。既に実行していますが、トラフィックが多すぎたため、キャッシュファイルの代わりにディスクファイルを使用したため、タイミングの比較が無意味になりました。キャッシュされたデータを使用して他のスヌープを実行し、ボックス間で他のトラフィックを実行しません。未定

さらに、ネットワーク関係者は、接続にトラフィックシェーピングまたは帯域幅リミッターがないと言います。


2
まず、nfsv4はデフォルトでudpではなくtcpで実行されます。
フィルホレンバック

3
AFAIK、solarisは、Linuxとは異なり、v3でもデフォルトでtcpをマウントします。v3のテストのために私はまた、明示的に「プロト= TCP」の試験が、いくつかの中でまたは「プロト= TCP」を含むなしv3で同じ性能を持っていた
カイルヘイリー

スイッチングインフラストラクチャとサーバーNICで既にジャンボフレームを有効にしましたか?
多項式

はい、ジャンボフレームがセットアップされ、検証されます。dtraceを使用すると、パケットサイズを確認できます。
カイルヘイリー

1
実際、Linuxはデフォルトでtcpでマウントするようになりました
janneb

回答:


4

NFS 4.1(マイナー1)は、より高速で効率的なプロトコルとして設計されており、以前のバージョン、特に4.0よりも推奨されています。

これには、クライアント側のキャッシュが含まれ、このシナリオには関係ありませんが、パラレルNFS(pNFS)が含まれます。大きな変更点は、プロトコルが現在ステートフルであることです。

http://www.netapp.com/us/communities/tech-ontap/nfsv4-0408.html

NetAppsを使用するときは、パフォーマンスのドキュメントから判断すると、このプロトコルが推奨されると思います。このテクノロジーは、Windows Vista +の日和見ロックに似ています。

NFSv4は、サーバーがファイルに対する特定のアクションをクライアントに委任して、データのより積極的なクライアントキャッシングを可能にし、ロック状態のキャッシングを可能にするという点で、以前のバージョンのNFSと異なります。サーバーは、ファイルの更新とロック状態の制御を委任を介してクライアントに譲ります。これにより、クライアントがさまざまな操作を実行し、データをローカルにキャッシュできるため、待ち時間が短縮されます。現在、読み取りと書き込みの2種類の委任が存在します。サーバーには、ファイルの競合が発生した場合にクライアントから委任をコールバックする機能があります。クライアントが委任を保持すると、データがローカルにキャッシュされているファイルに対して操作を実行して、ネットワークの待ち時間を回避し、I / Oを最適化できます。委任から生じるより積極的なキャッシングは、次の特性を持つ環境で大きな助けになります。

  • 頻繁に開閉する
  • 頻繁なGETATTR
  • ファイルロック
  • 読み取り専用共有
  • 高いレイテンシー
  • 高速クライアント
  • 多くのクライアントを備えた負荷の重いサーバー

NFS 4.1上のポインタのためのおかげで、私の知る限り、彼らは我々が4.0であるけれども
カイルヘイリー

1
実際には、クライアント側のキャッシュの変更は4.0で行われ、v4の抽出からわかるように、「NFSv4 ...デリゲート...クライアントへ」という書き込みの最大のパフォーマンスの違いになります。質問が読書に関するものであることに気付いた。この場合、このほとんどがどの程度関連するのかわかりません。
ピーター
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.