NFS v3 बनाम v4


11

मैं सोच रहा हूं कि एनएफएस वी 4 एनएफएस वी 3 की तुलना में इतना तेज क्यों होगा और अगर वी 3 पर कोई पैरामीटर है जो कि ट्विक किया जा सकता है।

मैं एक फाइल सिस्टम माउंट करता हूं

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-400MB / s पढ़ सकता हूं, लेकिन जब मैं vers=3dd में संस्करण बदलता हूं , रिमाउंट करता हूं और फिर से चलाता हूं तो मुझे केवल 90MB / s मिलते हैं । मैं जिस फ़ाइल से पढ़ रहा हूं वह एनएफएस सर्वर पर एक मेमोरी फाइल है। कनेक्शन के दोनों किनारे सोलारिस हैं और 10GbE NIC हैं। मैं सभी परीक्षणों के बीच रीमाउंट करके किसी भी क्लाइंट साइड कैशिंग से बचता हूं। मैं dtraceसर्वर पर यह देखने के लिए उपयोग करता था कि एनएफएस के माध्यम से कितनी तेजी से डेटा परोसा जा रहा है। दोनों v3 और v4 के लिए मैं बदल गया:

 nfs4_bsize
 nfs3_bsize

डिफ़ॉल्ट 32K से 1M (v4 पर मैंने अधिकतम 150K / 32K के साथ अधिकतम किया है) मैंने ट्विक करने की कोशिश की है

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_clusters

v3 के प्रदर्शन को बेहतर बनाने के लिए, लेकिन नहीं।

V3 पर अगर मैं चार समानांतर दौड़ता हूँ, तो 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

dd के v3 और v4 और तुलना करने पर स्नूप की योजना बनाने पर योजना। पहले ही कर चुके हैं, लेकिन बहुत अधिक ट्रैफ़िक था और मैंने कैश्ड फ़ाइल के बजाय डिस्क फ़ाइल का उपयोग किया, जिसने समय की तुलना को व्यर्थ बना दिया। कैश्ड डेटा के साथ अन्य स्नूप चलाएगा और बक्से के बीच कोई अन्य ट्रैफ़िक नहीं होगा। TBD

इसके अतिरिक्त नेटवर्क वालों का कहना है कि कनेक्शनों पर ट्रैफिक शेपिंग या बैंडविड्थ सीमा नहीं है।


2
एक बात के लिए अच्छी तरह से nfsv4 udp के बजाय डिफ़ॉल्ट रूप से tcp पर चलता है।
फिल होलेनबैक

3
AFAIK, सोलारिस, लिनक्स के विपरीत, v3 पर भी डिफ़ॉल्ट रूप से tcp को मापता है। V3 परीक्षणों के लिए, मैंने कुछ परीक्षणों में स्पष्ट रूप से "proto = tcp" भी किया था, लेकिन v3 पर समान प्रदर्शन किया था, जिसमें "proto = tcp" शामिल नहीं था
Kyle Hailey

क्या आपने पहले से ही स्विचिंग इन्फ्रास्ट्रक्चर और सर्वर एनआईसी पर जंबो फ्रेम को सक्षम किया है?
बहुपद

हां, जंबो फ्रेम स्थापित और सत्यापित हैं। Dtrace के साथ मैं पैकेट साइज देख सकता हूं।
काइल हैले

1
दरअसल, लिनक्स भी
janneb

जवाबों:


4

एनएफएस 4.1 (माइनर 1) को तेज और अधिक कुशल प्रोटोकॉल के लिए डिज़ाइन किया गया है और पिछले संस्करणों, विशेष रूप से 4.0 से अधिक की सिफारिश की गई है।

इसमें क्लाइंट-साइड कैशिंग शामिल है , और हालांकि इस परिदृश्य में प्रासंगिक नहीं है, समानांतर-एनएफएस (पीएनएफएस) । प्रमुख बदलाव यह है कि प्रोटोकॉल अब स्टेटफुल है।

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

मुझे लगता है कि यह NetApps का उपयोग करते समय अनुशंसित प्रोटोकॉल है, उनके प्रदर्शन प्रलेखन द्वारा देखते हुए। तकनीक विंडोज विस्टा + अवसरवादी लॉकिंग के समान है।

NFSv4 सर्वर को डेटा के अधिक आक्रामक क्लाइंट कैशिंग को सक्षम करने और लॉकिंग स्थिति की कैशिंग की अनुमति देने के लिए एक फ़ाइल पर एक क्लाइंट पर विशिष्ट कार्यों को प्रतिनिधि करने की अनुमति देकर NFS के पिछले संस्करणों से भिन्न होता है। एक सर्वर एक प्रतिनिधि के माध्यम से एक ग्राहक के लिए फ़ाइल अपडेट और लॉकिंग स्थिति पर नियंत्रण रखता है। यह क्लाइंट को विभिन्न ऑपरेशन और कैश डेटा को स्थानीय रूप से निष्पादित करने की अनुमति देकर विलंबता को कम करता है। वर्तमान में दो प्रकार के प्रतिनिधिमंडल मौजूद हैं: पढ़ना और लिखना। सर्वर में एक क्लाइंट से एक प्रतिनिधिमंडल को वापस बुलाने की क्षमता है, जिसमें फ़ाइल के लिए विवाद होना चाहिए। एक बार जब एक ग्राहक एक प्रतिनिधिमंडल रखता है, तो यह उन फ़ाइलों पर संचालन कर सकता है, जिनके डेटा को स्थानीय विलंबता से बचने और I / O को अनुकूलित करने के लिए स्थानीय रूप से कैश किया गया है। प्रतिनिधि के परिणामस्वरूप अधिक आक्रामक कैशिंग निम्नलिखित विशेषताओं के साथ वातावरण में एक बड़ी मदद हो सकती है:

  • बार-बार खुलता और बंद होता है
  • बार-बार GETATTRs
  • फ़ाइल लॉक करना
  • पढ़ें- केवल साझा
  • उच्च विलंबता
  • तेज ग्राहक
  • कई ग्राहकों के साथ भारी लोड सर्वर

NFS 4.1 पर संकेत देने वालों के लिए धन्यवाद, हालांकि I AFAIK के बाद वे 4.0 पर हैं
काइल हैली

1
दरअसल, क्लाइंट साइड कैशिंग परिवर्तन 4.0 के साथ आया था, और लेखन के लिए सबसे बड़ा प्रदर्शन अंतर हो सकता है, जैसा कि आप v4 अर्क से देख सकते हैं - "NFSv4 ... प्रतिनिधि ... एक ग्राहक के लिए"। सिर्फ पढ़ने के बारे में सवाल देखा गया था। मुझे यकीन नहीं है कि यह उस मामले के लिए कितना प्रासंगिक है।
पीटर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.