NFS v3 ve v4 karşılaştırması


11

NFS v4'ün neden NFS v3'ten çok daha hızlı olacağını ve v3'te tweaked olabilecek herhangi bir parametre olup olmadığını merak ediyorum.

Bir dosya sistemi monte ediyorum

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

ve sonra koş

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

200-400MB / s okuyabilirim ama sürümü değiştirdiğimde vers=3, yeniden takıp dd'yi yeniden çalıştırdığımda sadece 90MB / s alıyorum . Okuduğum dosya, NFS sunucusundaki bir bellek dosyasında. Bağlantının her iki tarafı Solaris ve 10GbE NIC'ye sahip. Tüm testler arasında yeniden montaj yaparak herhangi bir istemci tarafında önbellekleme önlemek. Ben kullanılan dtraceNFS aracılığıyla sunulmakta ne kadar hızlı veri ölçmek için sunucu üzerinde görmek için. Hem v3 hem de v4 için değiştim:

 nfs4_bsize
 nfs3_bsize

varsayılan 32K'dan 1M'ye (v4'de 32MB ile 150MB / s'de maks.) Tweaking'i denedim

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_clusters

v3 performansını artırmak için, ama gitmek yok.

Eğer dört paralel çalıştırırsam dd, verim 90MB / s'den 70-80MBs'ye iniyorsa, bu da sorunun bazı paylaşılan kaynak olduğuna inanmamı sağlıyor ve eğer öyleyse, bunun ne olduğunu merak ediyorum ve bunu artırabilirsem kaynak.

pencere boyutları almak için dtrace kodu:

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

Çıktı şuna benzer (bu özel durumdan değil):

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

bazı başlıklar

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

v3 ve v4 üzerindeki dd'lerin snoop'larını almayı ve karşılaştırmayı planlama. Zaten yaptım ama çok fazla trafik vardı ve zamanlamaları karşılaştırmak anlamsız hale önbellek dosyası yerine bir disk dosyası kullandım. Önbellekteki verilerle diğer snoop'ları çalıştıracak ve kutular arasında başka trafik olmayacak. TBD

Ayrıca ağ adamları bağlantılarda trafik şekillendirme veya bant genişliği sınırlayıcıları olmadığını söylüyor.


2
Bir şey için nfsv4 varsayılan olarak udp yerine tcp üzerinde çalışır.
Phil Hollenback

3
AFAIK, solaris, linux'un aksine, v3'de bile varsayılan olarak tcp'yi bağlar. V3 testleri için de bazı testlerde açıkça "proto = tcp" var ama v3 üzerinde "proto = tcp" olsun veya olmasın aynı performansa
Kyle Hailey

Anahtarlama altyapısı ve sunucu NIC'lerinde jumbo çerçeveleri zaten etkinleştirdiniz mi?
polinom

evet, jumbo çerçeveler ayarlanır ve doğrulanır. Dtrace ile paket boyutlarını görebiliyorum.
Kyle Hailey

1
Aslında, Linux varsayılan olarak tcp ile montajı da yapar
janneb

Yanıtlar:


4

NFS 4.1 (küçük 1) daha hızlı ve daha verimli bir protokol olacak şekilde tasarlanmıştır ve önceki sürümlere, özellikle 4.0'a göre önerilir.

Bu, istemci tarafı önbelleğe almayı içerir ve bu senaryoda geçerli olmasa da, paralel NFS (pNFS) . En büyük değişiklik, protokolün artık durumsal olmasıdır.

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

Performans belgelerine göre NetApp'leri kullanırken önerilen protokol olduğunu düşünüyorum. Teknoloji, Windows Vista + fırsatçı kilitlemeye benzer.

NFSv4, bir sunucunun verilerin daha agresif istemci önbelleğe alınmasını sağlamak ve kilitleme durumunun önbelleğe alınmasına izin vermek için bir dosyadaki belirli eylemleri bir istemciye devretmesine izin vererek önceki NFS sürümlerinden farklıdır. Sunucu, bir temsilci aracılığıyla dosya güncelleştirmelerinin denetimini ve kilitleme durumunu istemciye bırakır. Bu, istemcinin çeşitli işlemleri gerçekleştirmesine ve verileri yerel olarak önbelleğe almasına izin vererek gecikmeyi azaltır. Şu anda iki tür delegasyon mevcuttur: okuma ve yazma. Sunucu, bir dosya için çekişme olması durumunda istemciden bir temsilci geri arama yeteneğine sahiptir. İstemci bir temsilci bulundurduğunda, ağ gecikmesini önlemek ve G / Ç'yi optimize etmek için verileri yerel olarak önbelleğe alınan dosyalar üzerinde işlemler gerçekleştirebilir. Delegasyonlardan kaynaklanan daha agresif önbellekleme, aşağıdaki özelliklere sahip ortamlarda büyük bir yardımcı olabilir:

  • Sık açılıp kapanıyor
  • Sık GETATTR'ler
  • Dosya kilitleme
  • Salt okunur paylaşım
  • Yüksek gecikme süresi
  • Hızlı müşteriler
  • Birçok istemciye sahip yoğun yüklü sunucu

NFS 4.1'deki işaretçiler için teşekkürler, ancak AFAIK'te 4.0'dayız
Kyle Hailey

1
Aslında, istemci tarafı önbellek değişiklikleri 4.0 ile geldi ve v4 özü - "NFSv4 ... delegate ... delegate" dan görebileceğiniz gibi yazma için en büyük performans farkı olabilir. Sorunun okumakla ilgili olduğunu fark ettim. Bu durum için bunun çoğunun ne kadar alakalı olduğundan emin değilim.
Peter
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.