故障描述
在NFS服务器执行批量删除文件时,删除到特定文件会出现约90秒的卡顿现象。具体操作如下:
执行命令:strace -T rm -f reporters.2025-03*

通过perf工具跟踪系统调用生成的火焰图显示:

perf report查看的详细信息:

检查文件大小发现:
ll -th reporters.2025-03-08.20
-rw-r--r-- 1 root root 590 Mar 8 2025 reporters.2025-03-08.20
文件体积不足1KB,排除大小因素。
正常删除文件时的内核调用对比:

卡顿期间系统IO负载正常:

对比两台NFS客户端挂载参数基本一致:
# 卡顿机器挂载参数
(rw,nosuid,nodev,noexec,noatime,vers=3,rsize=32768,wsize=32768,namlen=255,hard,proto=tcp,timeo=60,retrans=2,sec=sys,mountaddr=10.0.0.1,mountvers=3,mountport=20048,mountproto=udp,local_lock=none,addr=10.0.0.1)
# 正常机器挂载参数
(rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.0.0.2,mountvers=3,mountport=20048,mountproto=udp,local_lock=none,addr=10.0.0.2)
排查过程
从挂载参数分析未发现直接影响删除操作的配置。通过深入分析和官方资料验证,发现问题的核心在于NFSv4引入的租约机制。

NFSv4版本新增了lease租约模式,官方文档说明:
除 pNFS 外,NFSv4.1 还提供:
会话目录委托与通知
多服务器命名空间
访问控制列表和自主访问控制
保留属性
SECINFO_NO_NAME
NFSv4引入租约和委托机制的主要目的是提升性能同时保证数据一致性。与NFSv3无状态设计不同,NFSv4允许服务端向客户端发放"委托书",客户端可在本地缓存读写操作,减少网络往返。当其他客户端需要访问文件时,服务端会向持有委托的客户端发送召回请求。
90秒超时机制:如果客户端无法响应召回请求,服务端会在租约超时(默认90秒)后强制废除委托。这正好解释了删除卡顿90秒的现象。
通过查看系统锁状态确认租约存在:
cat /proc/locks | more
1: DELEG ACTIVE READ 2458 fd:47:3758655664 0 EOF
2: DELEG ACTIVE READ 2458 fd:47:1612867788 0 EOF
其中DELEG标识表示文件存在委托租约,fd:47:xxx对应文件的inode号。
验证租约超时时间:
cat /proc/fs/nfsd/nfsv4leasetime
90
针对客户端无响应的情况,当前解决方案需要重启NFS服务端来清理僵尸锁文件:
# 运行状态下无法修改租约时间
echo 10 > /proc/fs/nfsd/nfsv4leasetime
-bash: echo: write error: Device or resource busy
# 停止服务后修改
systemctl stop nfs-server.service
echo 10 > /proc/fs/nfsd/nfsv4leasetime
systemctl start nfs-server.service
cat /proc/fs/nfsd/nfsv4leasetime
10
由于生产环境NFS服务端连接客户端众多,重启操作影响较大,目前只能通过后台缓慢清理异常锁文件。
NFSv3与v4委托功能对比
通过实验验证两个版本在委托租约功能上的差异:
NFSv3版本测试:
mount -t nfs -o vers=3 10.0.0.1:/data/test /mnt
创建并编辑文件后,服务端/proc/locks中未出现DELEG标识记录。


NFSv4版本测试:
mount -t nfs 10.0.0.1:/data/test /mnt
保持文件打开状态,服务端可见DELEG标识记录,且inode号对应一致。


实验证明NFSv3版本读写操作不会产生委托租约,而v4版本会建立租约机制,这也是导致删除卡顿的根本原因。在进行Linux系统性能分析时,这种版本差异需要特别注意。
验证重启清理僵尸锁记录
通过模拟环境验证重启NFS服务对僵尸锁文件的清理效果:
测试环境:
- 服务器A:NFS Server (10.0.0.1)
- 服务器B:NFS Client (10.0.0.2)
测试步骤:
-
客户端B通过v4版本挂载NFS目录
-
执行tail -f持续读取文件
-
服务端A确认存在DELEG记录:
grep -i dele /proc/locks
1: DELEG BREAKING READ 61855 fd:03:404751 0 EOF
-
客户端B阻断与A的网络连接:
iptables -I INPUT -s 10.0.0.1 -j DROP
-
服务端A尝试删除文件时出现卡顿:
rm -f mm111.log
# 操作卡住,需要强制终止
-
重启NFS服务后锁记录消失,删除操作正常完成:
systemctl restart nfs-server.service
grep -i dele /proc/locks
# 无输出,锁记录已清理
rm -f mm111.log
# 删除成功
这个实验证实了重启NFS服务能够有效清理因客户端异常断开产生的僵尸锁文件,但需要考虑运维管理中对服务可用性的影响。
版本兼容性说明
当客户端以v4版本挂载父目录时,其下所有子目录文件都会默认采用v4协议访问。验证结果如下:

这种网络文件系统的版本继承特性在实际部署时需要特别注意,避免因版本混用导致的性能问题。
总结
通过本次排查,深入理解了NFS不同版本在租约机制上的差异。NFSv4虽然提供了性能优化,但也引入了新的复杂度。在实际生产环境中,需要根据具体需求选择合适的版本,并建立相应的监控和故障处理机制。