Мне интересно, почему 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-400 МБ / с но когда я меняю версию на vers=3
, перемонтируйте и перезапустите диск, который я получаю только 90 МБ / с. Файл, из которого я читаю, находится в памяти на сервере NFS. Обе стороны подключения - Solaris и имеют сетевую карту 10GbE. Я избегаю кэширования на стороне клиента путем повторного монтирования между всеми тестами. я использовал dtrace
чтобы увидеть на сервере, чтобы измерить, насколько быстро данные передаются через NFS. И для v3, и для v4 я изменил:
nfs4_bsize
nfs3_bsize
от 32 КБ по умолчанию до 1 МБ (на v4 я максимизировал 150 МБ / с с 32 КБ) Я пробовал настраивать
чтобы улучшить производительность v3, но не пойдет.
На v3, если я запустил четыре параллельных dd
пропускная способность снижается с 90 МБ / с до 70-80 МБ, что наводит меня на мысль, что проблема заключается в каком-то общем ресурсе, и если да, то мне интересно, что это такое и могу ли я увеличить этот ресурс.
Код 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
Кроме того, сетевые специалисты говорят, что в соединениях нет ограничения трафика или ограничения полосы пропускания.
NFS 4.1 (младший 1) разработан как более быстрый и эффективный протокол и рекомендуется по сравнению с предыдущими версиями, особенно 4.0.
Это включает кеширование на стороне клиента, и хотя это не имеет отношения к этому сценарию, параллельный NFS (pNFS). Главное изменение заключается в том, что протокол теперь отслеживает состояние.
http://www.netapp.com/us/communities/tech-ontap/nfsv4-0408.html
Я считаю, что это рекомендуемый протокол при использовании NetApps, судя по документации по их производительности. Технология аналогична Windows Vista + гибкая блокировка.
NFSv4 отличается от предыдущих версий NFS тем, что позволяет серверу делегировать определенные действия с файлом клиенту, чтобы обеспечить более агрессивное кэширование данных клиентом и разрешить кэширование состояния блокировки. Сервер передает клиенту управление обновлениями файлов и состоянием блокировки через делегирование. Это уменьшает задержку, позволяя клиенту выполнять различные операции и кэшировать данные локально. В настоящее время существует два типа делегирования: чтение и запись. Сервер имеет возможность отозвать делегирование от клиента, если возникнет конфликт за файл. После того, как клиент получил делегирование, он может выполнять операции с файлами, данные которых были кэшированы локально, чтобы избежать задержки в сети и оптимизировать ввод-вывод. Более агрессивное кэширование в результате делегирования может оказаться большим подспорьем в средах со следующими характеристиками:
- Часто открывается и закрывается
- Частые GETATTR
- Блокировка файлов
- Совместное использование только для чтения
- Высокая задержка
- Быстрые клиенты
- Сильно загруженный сервер с большим количеством клиентов