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-400MB / s ได้ แต่เมื่อฉันเปลี่ยนเวอร์ชั่นเป็นvers=3remount และรัน dd อีกครั้งฉันจะได้90MB / sเท่านั้น ไฟล์ที่ฉันกำลังอ่านเป็นไฟล์หน่วยความจำในเซิร์ฟเวอร์ NFS ทั้งสองด้านของการเชื่อมต่อคือ Solaris และมี 10GbE NIC ฉันหลีกเลี่ยงการแคชฝั่งไคลเอ็นต์โดยการทำซ้ำระหว่างการทดสอบทั้งหมด ฉันเคยdtraceเห็นบนเซิร์ฟเวอร์เพื่อวัดความรวดเร็วของการให้บริการข้อมูลผ่าน NFS สำหรับ v3 และ v4 ฉันเปลี่ยนไป:

 nfs4_bsize
 nfs3_bsize

จากค่าเริ่มต้น 32K ถึง 1M (ใน v4 ฉันได้สูงสุดที่ 150MB / s ด้วย 32K) ฉันได้ลองปรับแต่ง

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_clusters

เพื่อปรับปรุงประสิทธิภาพ v3 แต่ไม่ต้องไป

ใน v3 ถ้าฉันเรียกใช้สี่ขนานddของปริมาณงานลดลงจาก 90MB / s เป็น 70-80MBs ซึ่งทำให้ฉันเชื่อว่าปัญหาคือทรัพยากรที่ใช้ร่วมกันและถ้าเป็นเช่นนั้นฉันสงสัยว่ามันคืออะไรและถ้าฉันสามารถเพิ่มที่ ทรัพยากร.

รหัส 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 ทำงานบน tcp โดยค่าเริ่มต้นแทน udp
Phil Hollenback

3
AFAIK, solaris ซึ่งแตกต่างจาก linux ติดตั้ง tcp ตามค่าเริ่มต้นแม้ใน v3 สำหรับการทดสอบ v3 ฉันยังได้ "proto = tcp" อย่างชัดเจนในการทดสอบบางอย่าง แต่มีประสิทธิภาพเหมือนกันใน v3 ที่มีหรือไม่มีการรวม "proto = tcp"
Kyle Hailey

คุณเปิดใช้งานเฟรมจัมโบ้บนโครงสร้างพื้นฐานการสลับและเซิร์ฟเวอร์ NIC แล้วหรือยัง
พหุนาม

ใช่กรอบจัมโบ้ถูกตั้งค่าและตรวจสอบแล้ว ด้วย dtrace ฉันสามารถดูขนาดแพ็คเก็ตได้
Kyle Hailey

1
ที่จริงแล้ว Linux ยังมีค่าเริ่มต้นที่จะติดตั้งด้วย tcp
janneb

คำตอบ:


4

NFS 4.1 (ผู้เยาว์ 1)ได้รับการออกแบบให้เป็นโปรโตคอลที่เร็วขึ้นและมีประสิทธิภาพยิ่งขึ้นและแนะนำให้ใช้กับเวอร์ชันก่อนหน้าโดยเฉพาะ 4.0

ซึ่งรวมถึงฝั่งไคลเอ็นต์แคชและแม้ว่าจะไม่เกี่ยวข้องในสถานการณ์สมมตินี้ขนาน NFS (pNFS) การเปลี่ยนแปลงที่สำคัญคือว่าโปรโตคอลตอนนี้ stateful

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

ฉันคิดว่ามันเป็นโปรโตคอลที่แนะนำเมื่อใช้ NetApps โดยพิจารณาจากเอกสารประสิทธิภาพ เทคโนโลยีนี้คล้ายคลึงกับการล็อกการฉวยโอกาสใน Windows Vista +

NFSv4 แตกต่างจาก NFS เวอร์ชันก่อนหน้าโดยอนุญาตให้เซิร์ฟเวอร์มอบหมายการดำเนินการเฉพาะบนไฟล์ให้กับไคลเอ็นต์เพื่อเปิดใช้งานการแคชข้อมูลเชิงรุกของลูกค้าและเพื่อให้สามารถแคชสถานะการล็อคได้ เซิร์ฟเวอร์ให้การควบคุมการอัปเดตไฟล์และสถานะการล็อคไปยังไคลเอนต์ผ่านการมอบหมาย สิ่งนี้ช่วยลดเวลาในการตอบสนองโดยการอนุญาตให้ไคลเอนต์ทำการดำเนินการต่าง ๆ และข้อมูลแคชภายในเครื่อง ปัจจุบันมีตัวแทนอยู่สองประเภท: อ่านและเขียน เซิร์ฟเวอร์มีความสามารถในการโทรกลับการมอบหมายจากไคลเอนต์ควรมีการช่วงชิงสำหรับไฟล์ เมื่อไคลเอนต์มีการมอบหมายมันสามารถดำเนินการกับไฟล์ที่ข้อมูลถูกแคชในเครื่องเพื่อหลีกเลี่ยงความหน่วงของเครือข่ายและเพิ่มประสิทธิภาพ I / O การแคชที่ดุดันมากขึ้นซึ่งเป็นผลมาจากการมอบหมายสามารถช่วยใหญ่ในสภาพแวดล้อมที่มีลักษณะดังต่อไปนี้:

  • บ่อยครั้งที่เปิดและปิด
  • GETATTRs บ่อย
  • การล็อคไฟล์
  • การแชร์แบบอ่านอย่างเดียว
  • เวลาแฝงสูง
  • ลูกค้าที่รวดเร็ว
  • โหลดเซิร์ฟเวอร์อย่างหนักพร้อมไคลเอนต์จำนวนมาก

ขอบคุณสำหรับคำแนะนำใน NFS 4.1 ถึงแม้ว่าฉันจะ AFAIK เราอยู่ใน 4.0
Kyle Hailey

1
ที่จริงแล้วการเปลี่ยนแปลงการแคชฝั่งไคลเอ็นต์นั้นมาพร้อมกับ 4.0 และอาจเป็นความแตกต่างด้านประสิทธิภาพที่ใหญ่ที่สุดสำหรับการเขียนตามที่คุณเห็นจากสารสกัด v4 - "NFSv4 ... ตัวแทน ... ไปยังลูกค้า" เพิ่งสังเกตเห็นว่าคำถามเกี่ยวกับการอ่าน ฉันไม่แน่ใจว่าส่วนใหญ่เกี่ยวข้องกับเรื่องนี้อย่างไร
ปีเตอร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.