NFS v3 versus v4

11

Saya bertanya-tanya mengapa NFS v4 akan jauh lebih cepat daripada NFS v3 dan jika ada parameter pada v3 yang bisa di-tweak.

Saya memasang sistem file

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

dan kemudian jalankan

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

Saya dapat membaca 200-400MB / s tetapi ketika saya mengubah versi ke vers=3, remount dan jalankan kembali dd saya hanya mendapatkan 90MB / s . File yang saya baca adalah file dalam memori di server NFS. Kedua sisi koneksi adalah Solaris dan memiliki 10GbE NIC. Saya menghindari caching sisi klien dengan remounting di antara semua tes. Saya biasa dtracemelihat di server untuk mengukur seberapa cepat data dilayani melalui NFS. Untuk v3 dan v4 saya mengubah:

 nfs4_bsize
 nfs3_bsize

dari default 32K ke 1M (pada v4 saya maxed di 150MB / s dengan 32K) Saya sudah mencoba tweaking

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_clusters

untuk meningkatkan kinerja v3, tetapi jangan pergi.

Pada v3 jika saya menjalankan empat paralel dd, throughput turun dari 90MB / s ke 70-80MB yang membuat saya percaya masalahnya adalah beberapa sumber daya bersama dan jika demikian, maka saya bertanya-tanya apa itu dan apakah saya dapat meningkatkannya sumber.

kode dtrace untuk mendapatkan ukuran jendela:

#!/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;
}

Outputnya seperti (bukan dari situasi khusus ini):

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

beberapa tajuk

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

berencana mengambil snoop tentang dd's over v3 dan v4 dan membandingkan. Sudah melakukannya tetapi ada terlalu banyak lalu lintas dan saya menggunakan file disk bukannya file cache yang membuat membandingkan waktu tidak ada artinya. Akan menjalankan pengintaian lain dengan data cache dan tidak ada lalu lintas lain di antara kotak. TBD

Selain itu orang-orang jaringan mengatakan tidak ada traffic traffic atau pembatas bandwidth pada koneksi.

Kyle Hailey
sumber
2
Nah untuk satu hal nfsv4 berjalan pada tcp secara default, bukan udp.
Phil Hollenback
3
AFAIK, solaris, tidak seperti linux, memasang tcp secara default bahkan pada v3. Untuk tes v3 saya juga secara eksplisit "proto = tcp" dalam beberapa tes tetapi memiliki kinerja yang sama pada v3 dengan atau tanpa menyertakan "proto = tcp"
Kyle Hailey
Sudahkah Anda mengaktifkan frame jumbo pada infrastruktur switching dan NIC server?
polinomial
ya, frame jumbo sudah diatur, dan diverifikasi. Dengan dtrace saya bisa melihat ukuran paket.
Kyle Hailey
1
Sebenarnya, Linux juga melakukan pemasangan secara default dengan tcp
janneb

Jawaban:

4

NFS 4.1 (minor 1) dirancang untuk menjadi protokol yang lebih cepat dan lebih efisien dan direkomendasikan dibandingkan versi sebelumnya, terutama 4.0.

Ini termasuk caching sisi klien , dan meskipun tidak relevan dalam skenario ini, parallel-NFS (pNFS) . Perubahan utama adalah bahwa protokol sekarang stateful.

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

Saya pikir itu adalah protokol yang direkomendasikan ketika menggunakan NetApps, dilihat dari dokumentasi kinerja mereka. Teknologi ini mirip dengan penguncian oportunistik Windows Vista +.

NFSv4 berbeda dari versi NFS sebelumnya dengan memungkinkan server untuk mendelegasikan tindakan spesifik pada file ke klien untuk memungkinkan caching data klien yang lebih agresif dan untuk memungkinkan caching keadaan penguncian. Server menyerahkan kontrol pembaruan file dan status penguncian ke klien melalui delegasi. Ini mengurangi latensi dengan memungkinkan klien untuk melakukan berbagai operasi dan cache data secara lokal. Dua jenis delegasi saat ini ada: membaca dan menulis. Server memiliki kemampuan untuk memanggil kembali delegasi dari klien seandainya ada perselisihan untuk suatu file. Setelah klien memegang delegasi, ia dapat melakukan operasi pada file yang datanya telah di-cache secara lokal untuk menghindari latensi jaringan dan mengoptimalkan I / O. Caching yang lebih agresif yang dihasilkan dari delegasi dapat sangat membantu dalam lingkungan dengan karakteristik berikut:

  • Sering dibuka dan ditutup
  • GETATTR Sering
  • Penguncian file
  • Berbagi hanya baca
  • Latensi tinggi
  • Klien cepat
  • Server dimuat dengan banyak klien
Steve-o
sumber
Terima kasih untuk petunjuk pada NFS 4.1 meskipun saya AFAIK mereka kita berada di 4.0
Kyle Hailey
1
Sebenarnya, perubahan caching sisi klien masuk dengan 4.0, dan mungkin perbedaan kinerja terbesar, untuk menulis, seperti yang Anda lihat dari ekstrak v4 - "NFSv4 ... delegate ... to a client". Hanya memperhatikan pertanyaannya adalah tentang membaca. Saya tidak yakin seberapa relevan sebagian besar dari ini untuk kasus itu.
Peter