NFS 是使用最广泛的 网络文件系统。对于中小型集群作为主存储,它非常容易设置并且性能相当好。如果应用程序不将它用于 I/O(例如/home),甚至可以将它用于更大的集群。关于 NFS 配置的最常见问题之一是如何针对性能和管理调整它,以及通常使用哪些配置选项。性能调优是一个很复杂的问题,因为性能是由许多不同的变量定义的,其中最重要的是如何衡量性能。但是,您至少可以确定提高 NFS 性能的选项。
此处主要有以下三个方面:
(1) NFS 性能调优选项
(2) 系统调优选项
(3) NFS 管理/策略选项
1. NFS 性能调整选项
同步与异步
NFS 守护进程的数量 ( nfsd )
块大小
超时和重传
FS Cache
挂载选项
2.系统调整选项
系统内存
MTU
TCP 参数调整
3. NFS 管理/策略选项
Subtree checking
Root squashing
1.1同步、异步
大多数人在 NFS 服务器上使用同步选项。对于同步写入,服务器仅在数据已写入稳定存储时才回复 NFS 客户端。许多人更喜欢此选项,因为如果 NFS 服务器出现故障或网络连接丢失,他们丢失数据的可能性很小。
异步模式允许服务器在处理完 I/O 请求后立即回复 NFS 客户端并将其发送到本地文件系统;也就是说,它不会等到数据写入稳定存储后才响应 NFS 客户端。这可以节省 I/O 请求的时间并提高性能。但是,如果 NFS 服务器在 I/O 请求到达磁盘之前崩溃,您可能会丢失数据。
当文件系统挂载到客户端时,可以设置同步或异步模式,只需将sync或async放在挂载命令行或NFS 文件系统的文件/etc/fstab中。如果要更改选项,首先必须卸载 NFS 文件系统,更改选项,然后重新安装文件系统。
两种操作模式之间的选择取决于您。如果您在某处有数据副本,您也许可以异步运行以获得更好的性能。如果您没有副本或者数据无法轻松或快速地复制,那么同步模式也许是更好的选择。
1.2 NFS 守护进程的数量
NFS 使用服务器上的线程来处理传入和传出的 I/O 请求。这些在进程表中显示为nfsd(NFS 守护进程)。使用线程有助于 NFS 扩展以处理大量客户端和大量 I/O 请求。默认情况下,NFS 仅以八个nfsd进程(八个线程)启动,鉴于当今的 CPU 具有非常多的核心数,这实际上是不够的。
您可以通过两种方式找到 NFS 守护进程的数量。首先是查看进程表并计算 NFS 进程的数量
ps -ef | grep nfs
第二种方法是查看 NFS 配置文件(例如,/etc/sysconfig/nfs或者/etc/nfs.conf)中的一个条目,上面写着RPCNFSDCOUNT,它告诉您服务器的 NFS 守护进程的数量。
/etc/sysconfig/nfs
***
# Number of nfs server processes to be started.
# The default is 8.
#RPCNFSDCOUNT=16
/etc/nfs.conf
***
[nfsd]
threads=8
如果 NFS 服务器有大量内核和大量内存,可以增加RPCNFSDCOUNT。我见过256用在16核128GB内存的NFS服务器上,跑得特别好。即使对于家庭集群,8 个 NFS 守护进程也非常小,您可能需要考虑增加数量。(4核8GB的NFS 服务器上,运行 64 个 NFS 守护进程。)
当有大量 NFS 客户端同时执行 I/O 时,就应该增加RPCNFSDCOUNT 。对于这种情况,还应该将 NFS 服务器上的内存量增加到一个较大的数字,例如 128 或 256GB。不要忘记,如果更改RPCNFSDCOUNT的值,则必须重新启动 NFS 才能使更改生效。
确定更多 NFS 线程是否有助于提高性能的一种方法是检查/proc/net/rpc/nfs中的数据以了解 NFS 守护进程的负载。以th开头的输出行列出了线程数,最后 10 个数字是秒数的直方图,前 10% 的线程忙碌,后 10%,依此类推。
理想情况下,最后两个数字为零或接近零,表示线程正忙并且没有“浪费”任何线程。如果最后两个数字相当高,您应该添加 NFS 守护进程,因为 NFS 服务器已成为瓶颈。如果最后两个、三个或四个数字为零,则可能没有使用某些线程。就我个人而言,如果我的系统有足够的内存,我不介意这种情况,因为我可能已经到了需要更多 NFS 守护进程的地步。
1.3 块大小设置
两个 NFS 客户端选项指定用于写入 ( wsize ) 和读取 ( rsize )的数据块的大小。如果您不指定块大小,则默认值由 NFS 版本和所使用的内核决定。如果您已经运行并配置了 NFS,检查当前块大小的最佳方法是运行命令
# cat /proc/mounts
...
172.16.17.251:/data/test /data nfs rw,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,port=30006,timeo=600,retrans=2,sec=sys,mountaddr=172.16.17.251,mountvers=3,mountport=30003,mountproto=udp,local_lock=none,addr=172.16.17.251 0 0
在 NFS 客户端上并查找wsize和rsize值。
rsize=1048576
wsize=1048576
块大小会影响创建和发送的数据包或远程过程调用。
如果应用程序混合使用 I/O 负载大小,则选择块大小可能需要进行一些试验。您可以通过更改客户端上的选项进行试验;在重新运行应用程序之前,您必须卸载并重新安装文件系统。不要害怕测试一系列块大小,从默认值开始并进入兆字节范围。
1.4 超时和重传
超时和重传选项,虽然乍一看不影响性能,但对 NFS 非常重要,尤其是对客户端。这些选项确定 NFS 客户端在重新传输数据包 ( timeo ) 之前等待多长时间,以及 NFS 客户端在重新启动整个过程之前尝试重新发送数据包 ( retrans )的次数。
timeo (超时)选项是 NFS 客户端在重新传输数据包(未收到 ACK)之前在 NFS 服务器上等待的时间量。timeo的值以十分之一秒为单位给出,因此如果timeo为5,则 NFS 客户端将等待 0.5 秒再重新传输。默认值为0.7 (0.07 秒),但您可以使用mount命令的timeo选项或通过编辑NFS 客户端上的/etc/fstab文件以指示timeo的值来调整该选项。
另一个选项retrans指定 NFS 客户端将尝试重新传输数据包的次数。如果值为5,客户端将重新发送 RPC 数据包五次,两次尝试之间等待timeo秒。如果在最后一次尝试后 NFS 服务器没有响应,您将收到一条消息Server not responding。NFS 客户端然后重置 RPC 传输尝试计数器并以相同的方式再次尝试(相同的timeo和retrans值)。
在拥塞的网络上,您经常会看到 RPC 数据包的重传。一个很好的判断方法是运行
# nfsstat -r
Server rpc stats:
calls badcalls badfmt badauth badclnt
0 0 0 0 0
Client rpc stats:
calls retrans authrefrsh
16 0 16
命令并查找标有retrans的列。如果数量很大,则网络可能非常拥塞。如果是这种情况,您可能希望增加timeo和retrans的值以增加尝试次数和 RPC 尝试之间的时间量。虽然执行此操作会降低 NFS 性能,但它可能有助于平衡网络流量,从而减少拥塞。根据经验,摆脱拥塞和丢包可以带来更好、更均匀的性能。
1.5FS缓存
您可能要考虑用来提高 NFS 客户端性能的另一个选项是FS-Cache,它将 NFS 客户端请求缓存在本地存储设备上,例如硬盘驱动器或 SSD,有助于提高 NFS 读取 I/O:驻留在本地 NFS 客户端意味着无需联系 NFS 服务器。
要使用 NFS 缓存,您必须通过将选项-o fsc添加到mount命令或/etc/fstab来显式启用它:
mount <nfs-share>:/ </mount/point> -o fsc
对 < /mount/point >的任何数据访问都将通过 NFS 缓存,除非文件是为直接 I/O 打开的,或者执行了写 I/O。
需要记住的重要一点是,FS-Cache 仅在 I/O 为读取时才起作用。FS-Cache 无法帮助处理直接 I/O(读取或写入)或 I/O 写入请求。但是,在很多情况下 FS-Cache 可以提供帮助。例如,如果您有一个需要从数据库或文件读取的应用程序,并且您正在运行同一应用程序的大量副本,FS-Cache 可能会有所帮助,因为每个节点都可以缓存数据库或文件。
最适合您的 NFS 配置的块大小主要取决于网络配置和执行 I/O 的应用程序。如果您的应用程序正在执行大量小 I/O,那么大块大小就没有意义。反之亦然。例如,如果要使用 32KB 的块传输 1MB 的数据,则数据将以相当多的块和相应大量的网络数据包发送。如果将块大小增加到 64KB,则网络上的块数和数据包数都会减少。
如果应用程序混合使用 I/O 负载大小,则选择块大小可能需要进行一些试验。您可以通过更改客户端上的选项进行试验;在重新运行应用程序之前,您必须卸载并重新安装文件系统。不要害怕测试一系列块大小,从默认值开始并进入兆字节范围。
1.6 挂载选项
Linux 中的mount命令有许多独立于文件系统的选项,可能能够提高性能。一些关键选项是:
noatime – 文件系统上的索引节点访问时间不更新。这有助于提高性能,因为文件的访问时间不会在每次访问文件时更新。
nodiratime – 目录 inode 在被访问时不会在文件系统上更新。这可以以与不更新文件访问时间相同的方式帮助提高性能。
relatime – 索引节点访问时间与文件的修改或更改时间相关,因此仅当先前的 atime(访问时间)早于修改或更改时间时,访问时间才会更新。
在使用这些选项之前,请阅读mount 手册页。您还需要决定访问时间是否值得准确跟踪。通过不跟踪或不准确地跟踪它,您可以提高性能。
2.1 系统内存
系统调整选项并不是真正的 NFS 调整选项,但系统更改可能会导致 NFS 性能发生变化。一般来说,Linux 及其服务喜欢内存,会尽可能多地占用系统内存。当然,如果系统需要它用于其他应用程序,则返回此内存,而不是让它浪费,如果是空闲的则将其用于缓冲区和高速缓存。
NFS 绝对是一种服务,尤其是在服务器上,它会使用尽可能多的缓冲区空间。使用这些缓冲区,NFS 可以合并 I/O 请求以提高带宽。因此,您可以添加到 NFS 服务器的物理内存越多,性能提高的可能性就越大,尤其是当您有大量 NFS 客户端同时访问服务器时。 问题是:您的 NFS 服务器需要多少内存?
由于目标相互冲突,答案不容易确定。理想情况下,您应该在服务器中放置尽可能多的内存。但是,如果预算有点紧张,那么您将不得不权衡是为 NFS 服务器购买最大容量的内存还是将资金投入系统的其他方面。您能否将 NFS 服务器上的内存从 512 GB 减少到 256 GB,或者购买一个额外的计算节点?这值得交易吗?答案取决于你。
然而,作为生产 HPC 系统的经验法则,我倾向于在 NFS 服务器上放置不少于 64GB 的内存,因为内存总体上更便宜。你总是可以使用更少的内存,也许是 16GB,但你可能会付出性能代价。但是,如果您的应用程序不执行太多 I/O,那么权衡可能是值得的。
如果您选择使用异步 NFS 模式,您将需要更多内存来利用async ,因为 NFS 服务器将首先将 I/O 请求存储在内存中,响应 NFS 客户端,然后通过让文件系统将其写入稳定存储。因此,您需要尽可能多的内存以获得最佳性能。
关于系统内存,我想补充的最后一个词是关于速度和内存通道的数量。为了让您的 NFS 服务器发挥出最后一点性能,您需要尽可能快的内存,同时认识到内存容量和内存性能之间的权衡。权衡的解决方案完全取决于您。如果内存容量不够大,您可能需要将内存速度降到下一个级别以增加容量。
为了获得最佳性能,您还需要一个具有最大内存通道数的 NFS 服务器,以增加服务器的整体内存带宽:
每个通道中至少有一个 DIMM,每个通道中的 DIMM 数量相同,并且每个通道中的 DIMM 大小和速度相同。同样,如果您使用异步模式,这可能更重要,但即使是同步模式也是一个好主意。
传输单元MTU
更改网络 MTU(最大传输单元)也是影响性能的好方法,但它不是 NFS 可调参数。相反,它是一个网络选项,您可以在系统上调整它以提高 NFS 性能。MTU 是可以通过以太网帧发送的最大数据量。默认 MTU 通常为1500(每帧 1,500 字节),但这可以很容易地更改。
为了对 NFS 性能产生最大影响,您必须更改 NFS 服务器和 NFS 客户端上的 MTU。在更改值以确定可以使用的最大 MTU 之前,您应该检查这两个系统。您还需要检查 NFS 服务器和 NFS 客户端之间的网络交换机和路由器可以容纳的最大 MTU。大多数交换机,甚至是非管理型“家庭”交换机,都可以容纳9000的 MTU (通常称为“巨型数据包”)。
MTU 大小可能非常重要,因为它决定了网络上的数据包碎片。如果您的块大小为 8KB 并且 MTU 为1500,则需要六个以太网帧来传输 8KB。如果将 MTU 增加到9000(9,000 字节),以太网帧的数量将减少到一个。
为了获得更好的 NFS 性能,最常见的建议是将 NFS 服务器和 NFS 客户端上的 MTU 都设置为9000(如果底层网络可以容纳的话)。几年前戴尔的一项研究比较了1500的 MTU与9000的 MTU 的效果。使用Netperf ,他们发现当使用9000的 MTU 时,带宽增加了大约 33% 。
TCP 调整
NFS 客户端和 NFS 服务器有很多TCP 参数可以调整。Internet 上的许多文章都讨论了 NFS 和一般网络流量的 TCP 调整选项。确切的值因您的具体情况而异。在这里,我想讨论两个提高 NFS 性能的选项:系统输入和输出队列。
增加输入和输出队列的大小允许通过 NFS 传输更多数据。实际上,您正在增加可以存储数据的缓冲区的大小。内存中可以存储的数据越多,NFS 处理它的速度就越快(即排队的数据越多)。NFS 服务器 NFS 守护进程共享相同的套接字输入和输出队列,因此如果队列较大,则所有 NFS 守护进程都有更多缓冲区并且可以更快地发送和接收数据。
对于输入队列,要修改的两个值是/proc/sys/net/core/rmem_default(读取队列的默认大小,以字节为单位)和/proc/sys/net/core/rmem_max(最大大小读取队列(以字节为单位)。这些值很容易修改:
echo 262144 > /proc/sys/net/core/rmem_default
echo 262144 > /proc/sys/net/core/rmem_max
这些命令将读取缓冲区大小更改为 256KiB(基数 2),这是 NFS 守护进程共享的。您可以对 NFS 守护程序共享的写入缓冲区执行相同的操作:
echo 262144 > /proc/sys/net/core/wmem_default
echo 262144 > /proc/sys/net/core/wmem_max
更改这些值后,您需要重新启动 NFS 服务器才能使它们生效。但是,如果您重新启动系统,这些值将消失并使用默认值。要使这些值在重新启动后仍然存在,您需要在/etc/sysctl.conf 文件中配置。
请注意,增加缓冲区大小并不一定意味着性能会提高。这只是意味着缓冲区大小更大。您将需要使用各种缓冲区大小测试您的应用程序,以确定增加缓冲区大小是否有助于提高性能。
Subtree Checking
假设 NFS 服务器已经从根文件系统导出了一个目录(例如/usr/local)。还假设它是系统根磁盘的一部分(即,它不在单独的分区或驱动器上)。在被攻击的 NFS 客户端上,攻击者可以猜测文件系统中但不在/usr/local/(NFS 导出目录)中的文件的文件句柄。现在您的 NFS 服务器已被破坏。
将选项subtree_check添加到 NFS 服务器上的导出检查正在访问的文件是否包含在导出目录中。在这种情况下,它会强制 NFS 服务器检查请求的文件是否位于/usr/local/中。或者,您可以在 NFS 服务器上指定选项no_subtree_check,它不会检查请求的文件是否在导出目录中。许多人认为subtree_check会对性能产生很大影响,但最终决定权在您。对于配置和您的情况,性能是否比安全更重要?
克服对subtree_check需求的一种方法是将导出的目录放在单独的分区或单独的驱动器上,以防止流氓用户猜测文件系统之外的任何文件句柄。您应该对驱动器空间进行分区,并为要导出的目录指定一个特定的挂载点。例如,如果要导出/usr/local/,它应该有自己的存储分区(或驱动器)并作为/usr/local安装在 NFS 服务器上。通过这样做,破解者无法猜测特定导出之外的文件句柄。
Root Squashing
默认情况下,用户root被“压缩”给用户nobody,以便 NFS 访问被划分。这一点很重要,因为如果恶意用户从某种媒体(例如 USB 记忆棒)引导系统,则该用户可以是该系统的根用户,然后可以更改 IP 地址以访问系统、挂载文件系统, 并从服务器复制数据。但是,如果root被压缩到用户nobody,那么root将拥有所有用户的相同权限,从而防止受损系统允许root从您的系统中提取数据。
另一方面,如果您希望root能够访问 NFS 挂载的文件系统,您可以将选项no_root_squash添加到文件/etc/exports以允许 root 访问。请注意,如果有人重新启动您的系统以获得 root 访问权限,他们可能会复制(窃取)数据。
执行man exports命令,然后切换到文件结尾,可以快速查看如下样例格式:
nfs共享参数 参数作用
rw 客户端对服务端共享目录有读写权限
ro 只读权限(客户端无法写入文件)
root_squash 当NFS客户端以root管理员访问时,映射为NFS服务器的匿名用户(默认设置)
no_root_squash 当NFS客户端以root管理员访问时,映射为NFS服务器的root管理员(不常用,有安全问题)
all_squash 无论NFS客户端使用什么账户访问,均映射为NFS服务器的匿名用户nfsnobody(常用)
no_all_squash 无论NFS客户端使用什么账户访问,都不进行压缩
sync 同时将数据写入到内存与硬盘中,保证不丢失数据
async 优先将数据保存到内存,然后再写入硬盘;这样效率更高,但可能会丢失数据
anonuid 配置all_squash使用,指定NFS的用户UID
anongid 配置all_squash使用,指定NFS的用户GID
# squash:v 去除、控制
# anonuid和anongid说明
参数以anon*开头即指anonymous匿名用户,这个用户的UID默认值通常为nfsnobody的UID值,也可以自行设置这个UID值。
在多NFS Clients时,如多台Web Server共享一个NFS目录,这个参数可以使不同的NFS Clients写入的数据对所有NFS Clients保持同样的用户权限。即统一用户、统一权限时有用。
安全优化:
在企业工作场景,通常情况NFS服务器共享的只是普通静态数据(图片、附件、视频),不需要执行suid、exec等权限,挂载的这个文件系统只能作为数据存取之用,无法执行程序,对于客户端来讲增加了安全性。例如: 很多木马篡改站点文件都是由上传入口上传的程序到存储目录,然后执行的。
# 通过mount -o指定挂载参数,禁止使用suid,exec,增加安全性能
# mount -t nfs -o nosuid,noexec,nodev 172.16.1.31:/data /mnt
注:通过mount -o指定参数效果与在/etc/fstab里指定参数是一样的,网络文件系统和本地的文件系统效果也是一样的。
# 禁止更新目录及文件时间戳
mount -t nfs -o noatime,nodiratime 172.16.1.31:/data /mnt
noatime、nodiratime 这两个选项是说在读写磁盘的时候,不更新文件和目录的时间戳(不更新文件系统中文件对应 inode 信息),这样就可以減少和磁盘系统的交互,提升读取和写入磁盘的效率,因为磁盘是机械的,每次读写都会消耗磁盘 I/O,而更新文件时间歡对于工作数据必要性不大,最大的问题是增加了访问磁盘I/O的次数,以致拖慢系统性能。
# 安全加性能优化
mount -t nfs -o noatime,nodiratime,nosuid,noexec,nodev 172.16.1.31:/data /mnt
内核优化:
# 下面是优化选项说明
- /proc/sys/net/core/rmem_default:该文件指定了接收套接字缓冲区大小的默认值(以字节为单位),默认设置:124928。
- /proc/sys/net/core/rmem_ max:该文件指定了接收套接字缓冲区大小的最大值(以字节为单位),默认设置:124928。
- /proc/sys/net/core/wmem_default:该文件指定了发送套接字缓冲区大小的默认值(以字节为单位),默认设置:124928
- /proc/sys/net/core/wmem_max:该文件指定了发送套接字缓冲区大小的最大值(以字节为单位),默认设置:124928
上述文件对应的具体内核优化命令如下:
cat >>/etc/sysctl.conf<<EOF
net.core.wmem default = 8388608
net.core.rmem default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
EOF
sysctl -p
其他优化:
1)硬件:SAS/SSD 磁盘,购买多个。硬件RAID,制作RAID5 或 RAID10。网卡吞吐量要大,至少千兆(多块 Bond)。
2)大型网站 NFS 网络文件系统的替代软件为分布式文件系统 MooseFS、 GlusterFS、FastDFS 等3)阿里云对应的存储服务 NAS 服务,还有OSS对象存储
NFS优缺点小结
# 1、NFS存储优点
1)NFS文件系统简单易用、方便部署、数据可靠、服务稳定、满足中小企业需求。(2000w日pv以下网站没问题)
2)NFS文件系统内存放的数据都在文件系统之上,所有数据都是能看得见。
# 2、NFS存储局限
1)存在单点故障, 如果nfs服务器宕机,所有客户端都不能访问。
解决:需加backup机器,维护麻烦web->nfs()->backup
2)NFS数据明文, NFS并不对数据完整性做任何校验。
3)客户端挂载NFS服务没有密码验证, 安全性一般(内网使用)
# 3、NFS应用建议
1)生产场景应将静态数据(比如:jpg\png\mp4\avi\css\js)尽可能往前端推,减少后端NFS存储压力。
比如使用CDN加速以及内网搭建文件缓存服务(Squid、Nginx、Varnish)
2)多个目录挂载到不同NFS服务器上(即NFS拆分为多台)
3)使用分布式文件系统(如MFS、FastDFS)
4)如果没有缓存或架构本身历史遗留问题太大, 在多存储也无用
转载自https://blog.csdn.net/qq_34777982/article/details/130592781
网友评论