NFS v3 so với v4


11

Tôi tự hỏi tại sao NFS v4 sẽ nhanh hơn NFS v3 rất nhiều và nếu có bất kỳ tham số nào trên v3 có thể được điều chỉnh.

Tôi gắn kết một hệ thống tập tin

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

và sau đó chạy

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

Tôi có thể đọc 200-400MB / s nhưng khi tôi thay đổi phiên bản thành vers=3, phát lại và chạy lại dd tôi chỉ nhận được 90MB / s . Tệp tôi đang đọc là một tệp trong bộ nhớ trên máy chủ NFS. Cả hai mặt của kết nối là Solaris và có 10GbE NIC. Tôi tránh bất kỳ bộ nhớ đệm phía máy khách nào bằng cách nối lại giữa tất cả các bài kiểm tra. Tôi đã từng dtracethấy trên máy chủ để đo tốc độ dữ liệu được phục vụ thông qua NFS. Đối với cả v3 và v4 tôi đã thay đổi:

 nfs4_bsize
 nfs3_bsize

từ mặc định 32K đến 1M (trên v4 tôi đã đạt tối đa 150MB / giây với 32K) Tôi đã thử điều chỉnh

  • nfs3_max_threads
  • clnt_max_conns
  • nfs3_async_cl cluster

để cải thiện hiệu suất v3, nhưng không đi.

Trên v3 nếu tôi chạy bốn song song dd, thông lượng giảm từ 90MB / s xuống 70-80 MB khiến tôi tin rằng vấn đề là một số tài nguyên được chia sẻ và nếu vậy, tôi tự hỏi đó là gì và liệu tôi có thể tăng nó không nguồn.

mã dtrace để có được kích thước cửa sổ:

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

Đầu ra trông giống như (không phải từ tình huống cụ thể này):

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

một số tiêu đề

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

lập kế hoạch lấy snoop của dd trên v3 và v4 và so sánh. Đã thực hiện nó nhưng có quá nhiều lưu lượng truy cập và tôi đã sử dụng một tệp đĩa thay vì một tệp được lưu trong bộ nhớ cache khiến việc so sánh thời gian trở nên vô nghĩa. Sẽ chạy các snoop khác với dữ liệu được lưu trong bộ nhớ cache và không có lưu lượng khác giữa các hộp. TBD

Ngoài ra, các nhà mạng nói rằng không có định hình lưu lượng hoặc giới hạn băng thông trên các kết nối.


2
Vâng, một điều nfsv4 chạy trên tcp theo mặc định thay vì udp.
Phil Hollenback

3
AFAIK, solaris, không giống như linux, gắn kết tcp theo mặc định ngay cả trên v3. Đối với các thử nghiệm v3, tôi cũng rõ ràng "proto = tcp" trong một số thử nghiệm nhưng có hiệu suất tương tự trên v3 có hoặc không bao gồm "proto = tcp"
Kyle Hailey

Bạn đã kích hoạt các khung khổng lồ trên cơ sở hạ tầng chuyển mạch và các máy chủ NIC chưa?
đa thức

có, khung jumbo được thiết lập và xác minh. Với dtrace tôi có thể thấy kích thước gói.
Kyle Hailey

1
Trên thực tế, Linux cũng mặc định gắn kết với tcp
janneb

Câu trả lời:


4

NFS 4.1 (nhỏ 1) được thiết kế để trở thành một giao thức nhanh hơn và hiệu quả hơn và được khuyên dùng so với các phiên bản trước, đặc biệt là 4.0.

Điều này bao gồm bộ nhớ đệm phía máy khách và mặc dù không liên quan trong kịch bản này, song song NFS (pNFS) . Sự thay đổi lớn là giao thức hiện có trạng thái.

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

Tôi nghĩ rằng đó là giao thức được đề xuất khi sử dụng NetApps, đánh giá bằng tài liệu hiệu suất của họ. Công nghệ này tương tự như Windows Vista + khóa cơ hội.

NFSv4 khác với các phiên bản trước của NFS bằng cách cho phép máy chủ ủy quyền các hành động cụ thể trên tệp cho khách hàng để cho phép bộ đệm dữ liệu của khách hàng tích cực hơn và cho phép lưu vào trạng thái khóa. Một máy chủ nhượng quyền kiểm soát các cập nhật tệp và trạng thái khóa cho máy khách thông qua một ủy quyền. Điều này làm giảm độ trễ bằng cách cho phép máy khách thực hiện các hoạt động khác nhau và dữ liệu bộ đệm cục bộ. Hai loại đoàn hiện đang tồn tại: đọc và viết. Máy chủ có khả năng gọi lại một phái đoàn từ máy khách nếu có sự tranh chấp cho một tệp. Khi khách hàng giữ một ủy quyền, nó có thể thực hiện các thao tác trên các tệp có dữ liệu được lưu trữ cục bộ để tránh độ trễ mạng và tối ưu hóa I / O. Bộ nhớ đệm tích cực hơn mà kết quả từ các đoàn có thể là một trợ giúp lớn trong các môi trường với các đặc điểm sau:

  • Thường xuyên mở và đóng
  • GETATTR thường xuyên
  • Khóa tập tin
  • Chia sẻ chỉ đọc
  • Độ trễ cao
  • Khách hàng nhanh
  • Máy chủ tải nặng với nhiều khách hàng

Cảm ơn các con trỏ trên NFS 4.1 mặc dù tôi AFAIK chúng tôi đang ở 4.0
Kyle Hailey

1
Trên thực tế, các thay đổi bộ nhớ đệm phía máy khách đã xuất hiện với 4.0 và có thể là sự khác biệt lớn nhất về hiệu suất, như bạn có thể thấy từ trích xuất v4 - "NFSv4 ... ủy thác ... cho khách hàng". Chỉ cần chú ý câu hỏi là về việc đọc. Tôi không chắc phần lớn điều này có liên quan đến trường hợp đó.
Peter
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.