我在ESXi中的NFS数据存储上遇到了大约五秒钟的 fsync延迟,这是由某些VM触发的。我怀疑这可能是由使用NCQ / TCQ的VM引起的,因为在虚拟IDE驱动器中不会发生这种情况。
可以使用fsync-tester(由Ted Ts'o)和ioping复制。例如,使用带有8GB磁盘的Grml实时系统:
Linux 2.6.33-grml64:
root@dynip211 /mnt/sda # ./fsync-tester
fsync time: 5.0391
fsync time: 5.0438
fsync time: 5.0300
fsync time: 0.0231
fsync time: 0.0243
fsync time: 5.0382
fsync time: 5.0400
[... goes on like this ...]
那是5秒,而不是毫秒。甚至在同一主机和数据存储上运行的不同VM上创建IO延迟:
root@grml /mnt/sda/ioping-0.5 # ./ioping -i 0.3 -p 20 .
4096 bytes from . (reiserfs /dev/sda): request=1 time=7.2 ms
4096 bytes from . (reiserfs /dev/sda): request=2 time=0.9 ms
4096 bytes from . (reiserfs /dev/sda): request=3 time=0.9 ms
4096 bytes from . (reiserfs /dev/sda): request=4 time=0.9 ms
4096 bytes from . (reiserfs /dev/sda): request=5 time=4809.0 ms
4096 bytes from . (reiserfs /dev/sda): request=6 time=1.0 ms
4096 bytes from . (reiserfs /dev/sda): request=7 time=1.2 ms
4096 bytes from . (reiserfs /dev/sda): request=8 time=1.1 ms
4096 bytes from . (reiserfs /dev/sda): request=9 time=1.3 ms
4096 bytes from . (reiserfs /dev/sda): request=10 time=1.2 ms
4096 bytes from . (reiserfs /dev/sda): request=11 time=1.0 ms
4096 bytes from . (reiserfs /dev/sda): request=12 time=4950.0 ms
当我将第一个VM移到本地存储时,它看起来非常正常:
root@dynip211 /mnt/sda # ./fsync-tester
fsync time: 0.0191
fsync time: 0.0201
fsync time: 0.0203
fsync time: 0.0206
fsync time: 0.0192
fsync time: 0.0231
fsync time: 0.0201
[... tried that for one hour: no spike ...]
我尝试过的事情没有什么区别:
- 测试了多个ESXi版本:381591、348481、260247
- 在不同的硬件,不同的Intel和AMD盒上进行了测试
- 在不同的NFS服务器上进行测试,都显示出相同的行为:
- OpenIndiana b147(始终或禁用ZFS同步:没有区别)
- OpenIndiana b148(始终或禁用ZFS同步:没有区别)
- Linux 2.6.32(同步或异步:没有区别)
- NFS服务器是在同一台计算机上(作为虚拟存储设备)还是在另一台主机上,这没有什么区别
来宾OS经过测试,显示问题:
- Windows 7 64位(使用CrystalDiskMark,延迟峰值通常发生在准备阶段)
- Linux 2.6.32(fsync-tester + ioping)
- Linux 2.6.38(fsync-tester + ioping)
我无法在Linux 2.6.18 VM上重现此问题。
另一个解决方法是使用虚拟IDE磁盘(相对于SCSI / SAS),但这会限制性能和每个VM的驱动器数量。
更新2011-06-30:
如果应用程序在fsync之前写入多个小块,则延迟峰值似乎更经常发生。例如,fsync-tester执行此操作(strace输出):
pwrite(3, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"..., 1048576, 0) = 1048576
fsync(3) = 0
ioping在准备文件时会这样做:
[lots of pwrites]
pwrite(3, "********************************"..., 4096, 1036288) = 4096
pwrite(3, "********************************"..., 4096, 1040384) = 4096
pwrite(3, "********************************"..., 4096, 1044480) = 4096
fsync(3) = 0
ioping的设置阶段几乎总是挂起,而fsync-tester有时可以正常工作。有人能够更新fsync-tester来编写多个小块吗?我的C技能很烂;)
更新2011-07-02:
iSCSI不会发生此问题。我在OpenIndiana COMSTAR iSCSI服务器上尝试了此操作。但是iSCSI无法让您轻松访问VMDK文件,因此您可以在具有快照和rsync的主机之间移动它们。
更新2011-07-06:
这是Wireshark捕获的一部分,该捕获由同一vSwitch上的第三个VM捕获。所有这些都发生在同一主机上,不涉及物理网络。
我已经在20左右开始ioping。直到五秒钟的延迟结束,才发送任何数据包:
No. Time Source Destination Protocol Info
1082 16.164096 192.168.250.10 192.168.250.20 NFS V3 WRITE Call (Reply In 1085), FH:0x3eb56466 Offset:0 Len:84 FILE_SYNC
1083 16.164112 192.168.250.10 192.168.250.20 NFS V3 WRITE Call (Reply In 1086), FH:0x3eb56f66 Offset:0 Len:84 FILE_SYNC
1084 16.166060 192.168.250.20 192.168.250.10 TCP nfs > iclcnet-locate [ACK] Seq=445 Ack=1057 Win=32806 Len=0 TSV=432016 TSER=769110
1085 16.167678 192.168.250.20 192.168.250.10 NFS V3 WRITE Reply (Call In 1082) Len:84 FILE_SYNC
1086 16.168280 192.168.250.20 192.168.250.10 NFS V3 WRITE Reply (Call In 1083) Len:84 FILE_SYNC
1087 16.168417 192.168.250.10 192.168.250.20 TCP iclcnet-locate > nfs [ACK] Seq=1057 Ack=773 Win=4163 Len=0 TSV=769110 TSER=432016
1088 23.163028 192.168.250.10 192.168.250.20 NFS V3 GETATTR Call (Reply In 1089), FH:0x0bb04963
1089 23.164541 192.168.250.20 192.168.250.10 NFS V3 GETATTR Reply (Call In 1088) Directory mode:0777 uid:0 gid:0
1090 23.274252 192.168.250.10 192.168.250.20 TCP iclcnet-locate > nfs [ACK] Seq=1185 Ack=889 Win=4163 Len=0 TSV=769821 TSER=432716
1091 24.924188 192.168.250.10 192.168.250.20 RPC Continuation
1092 24.924210 192.168.250.10 192.168.250.20 RPC Continuation
1093 24.924216 192.168.250.10 192.168.250.20 RPC Continuation
1094 24.924225 192.168.250.10 192.168.250.20 RPC Continuation
1095 24.924555 192.168.250.20 192.168.250.10 TCP nfs > iclcnet_svinfo [ACK] Seq=6893 Ack=1118613 Win=32625 Len=0 TSV=432892 TSER=769986
1096 24.924626 192.168.250.10 192.168.250.20 RPC Continuation
1097 24.924635 192.168.250.10 192.168.250.20 RPC Continuation
1098 24.924643 192.168.250.10 192.168.250.20 RPC Continuation
1099 24.924649 192.168.250.10 192.168.250.20 RPC Continuation
1100 24.924653 192.168.250.10 192.168.250.20 RPC Continuation
第二次更新2011-07-06:
TCP窗口大小似乎有一些影响。使用FreeNAS(基于FreeBSD)作为NFS服务器,我无法重现此问题。Wireshark捕获显示TCP窗口定期更新为29127字节。我没有在OpenIndiana上看到它们,默认情况下使用更大的窗口大小。
如果我在OpenIndiana中设置以下选项并重新启动NFS服务器,我将不再重现此问题:
ndd -set /dev/tcp tcp_recv_hiwat 8192 # default is 128000
ndd -set /dev/tcp tcp_max_buf 1048575 # default is 1048576
但这会降低性能:从/ dev / zero到dd_rescue的文件写入速度从170MB / s变为80MB / s。
更新2011-07-07:
我已经上传了这个tcpdump捕获(可以使用Wireshark分析)。在这种情况下,192.168.250.2是NFS服务器(OpenIndiana b148),而192.168.250.10是ESXi主机。
我在此捕获期间测试过的东西:
开始“ ioping -w 5 -i 0.2”。在时间30暂停5秒,在时间40完成。
开始“ ioping -w 5 -i 0.2”。在时间60,设置已挂起5秒钟,并在时间70结束。
在时间90开始“ fsync-tester”,输出如下,在时间120停止:
fsync time: 0.0248
fsync time: 5.0197
fsync time: 5.0287
fsync time: 5.0242
fsync time: 5.0225
fsync time: 0.0209
第二次更新2011-07-07:
测试了另一个NFS服务器VM,这次是NexentaStor 3.0.5社区版:显示相同的问题。
更新2011-07-31:
我还可以在新的ESXi内部版本4.1.0.433742上重现此问题。