NFS 缓存意外过期

NFS 缓存意外过期

我需要在高延迟、低吞吐量链接上构建 NFS4 + CacheFilesd 设置,其中本地缓存永不过期。唯一的失效语义必须是更新某些内容时 NFS 服务器回调(顺便说一句,这工作正常,服务器文件上的更改会立即传递到客户端)。此安装是只读的,因此没有锁定。

问题:尽管它始终会从本地缓存中正确读取所请求的文件,但如果在过去 60 秒左右未访问过该文件,则无论是否设置了 actimeo=86400,它都会继续获取文件属性。这似乎与文件打开的频率有关,因为只要我保持每 50 秒或更短时间打开它,它就可以正常工作。

概念证明:

(服务器网络延迟被人为设置为 2000 毫秒,这样我可以清楚地确定何时执行属性检查)

在每个请求按预期产生 100% 缓存命中后,等待 50 秒。这将无限期地持续下去:

root@client:~# while : ; do /usr/bin/time -f%e cat /nfs-mount/2bytes-file > /dev/null ; sleep 50 ; done
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00
0.00

现在将请求之间的延迟设置为 70 秒,看看结果有多不一致:

root@client:~# while : ; do /usr/bin/time -f%e cat /nfs-mount/2bytes-file > /dev/null ; sleep 70 ; done
0.00
0.00
0.00
0.00
0.00
0.00
6.00 # <- Attributes fetched. Debug log recorded "NFS: nfs_update_inode(0:69/68697599 fh_crc=0xb9b7a69e ct=2 info=0x26040)" 
4.00 # <- Attributes fetched. Debug log recorded "NFS: nfs_update_inode(0:69/68697599 fh_crc=0xb9b7a69e ct=2 info=0x26040)" 
0.00
0.00
0.00
6.00 # <- Attributes fetched. Debug log recorded "NFS: nfs_update_inode(0:69/68697599 fh_crc=0xb9b7a69e ct=2 info=0x26040)" 
4.00 # <- Attributes fetched. Debug log recorded "NFS: nfs_update_inode(0:69/68697599 fh_crc=0xb9b7a69e ct=2 info=0x26040)" 
0.00
0.00
0.00

此外,当发生这些延迟时,nfsstats 会添加一个额外的“getattr”:

create       delegpurge   delegreturn  getattr      getfh        link         
2         0% 0         0% 82        0% 177063   10% 87644     5% 0         0%

最后,当延迟设置为 110 秒或更长时间时,由于某种原因,每个请求最终都会在服务器上进行检查:

root@client:~# while : ; do /usr/bin/time -f%e cat /nfs-mount/2bytes-file > /dev/null ; sleep 110 ; done                                            
6.00
6.00
6.00
6.00
6.00
6.00
6.00

我通过使用 nginx 而不是“cat”并通过“ioping”通过 HTTP 提供这个 2 字节长的文件,成功地重现了完全相同的行为。

Cachefiled 不会自行清除任何内容,因为其分区中有足够的空间:

/dev/vdb                20G  3,0G   16G  17% /disk2/fscache

我知道它只是访问文件的元数据而不是内容本身,因为当我对 2GB 文件(大于客户端的物理内存大小)执行相同的测试时,它挂起 2 秒(网络建立的延迟) )然后它开始按预期从磁盘读取 Cachefilesd 本地缓存文件。

我真的不明白在这 1-2 分钟内发生了什么导致客户端重新检查服务器是否有更新,这破坏了我设置的目的。

/etc/导出:

/cache 192.168.122.234(ro,async,no_subtree_check)

客户端挂载:

root@client:~# mount -t nfs4 -o lookupcache=all,actimeo=86400,nocto,ro,intr,soft,proto=tcp,async,fsc 192.168.122.1:/cache /nfs-mount
root@client:~# cat /proc/mounts | grep nfs
192.168.122.1:/cache /nfs-mount nfs4 ro,relatime,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=86400,acregmax=86400,acdirmin=86400,acdirmax=86400,soft,nocto,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=192.168.122.234,fsc,local_lock=none,addr=192.168.122.1 0 0

服务器是Centos 7,客户端是Ubuntu 16.04。软件包是从发行版的存储库中获取的。

root@client:~# dpkg -l | grep nfs ii libnfsidmap2:amd64 0.25-5 amd64 NFS idmapping 库 ii nfs-common 1:1.2.8-9ubuntu12 amd64 客户端和服务器通用的 NFS 支持文件 ii nfs4-acl-tools 0.3.3-3 amd64 命令行和 GUI ACL 实用程序对于 NFSv4 客户端

我也尝试过使用Ubuntu作为服务器和CentOS 7作为客户端,但没有成功。

相关内容