14.9.内核参数优化

14.9.1.文件/进程优化

14.9.1.1. kern.maxfiles

可根据系统的要求来提高或降低 sysctl(8) 变量 kern.maxfiles。这个变量表示系统中文件描述符的最大数量。当文件描述符表已满时,file: table is full 会在系统消息缓冲区中反复显示,可以用 dmesg(8) 查看。

每个打开的文件、套接字或 fifo 都占用一个文件描述符。大规模的生产型服务器可能很容易需要成千上万的文件描述符,这取决于同时运行的服务的种类和数量。

在较早的 FreeBSD 版本中,kern.maxfiles 的默认值来自于内核配置文件中的 maxuserskern.maxfiles 的增长与 maxusers 的值成比例。当编译一个定制内核时,应根据系统的使用情况来设置这个内核配置选项。从这个数字来看,内核被赋予了大部分的预定义优化。即使一台生产机器可能没有 256 个并发用户,但所需要的资源可能与一个高规模的网络服务器相似。

sysctl(8) 只读变量 kern.maxusers 在启动时根据系统中可用的内存量自动确定大小,也可以在运行时通过检查 kern.maxusers 的值来确定。有些系统需要更大或更小的 kern.maxusers 值,64、128 和 256 的值多为常见。除非需要大量的文件描述符,否则不建议超过 256。许多被 kern.maxusers 设置为默认值的可调整值可以在启动时或运行时在 /boot/loader.conf 中被单独重新设置。请参考 loader.conf(5)/boot/defaults/loader.conf 以了解更多细节和一些提示。

在较早的版本中,如果 maxusers 被设置为 0(注 2),系统会自动进行调整。在设置这个选项时,至少要把 maxusers 设置为 4,特别是在系统运行 Xorg 或用来编译软件的情况下。maxusers 设置的最重要的表是最大进程数,它被设置为 20 + 16 * maxusers。如果 maxusers 被设置为 1,则只能有 36 个同时进行的进程,包括系统在启动时启动的 18 个左右的进程和 Xorg 使用的 15 个左右的进程。即使是一个简单的任务,比如阅读一个手册页面,也会启动 9 个进程来过滤、解压和查看它。将 maxusers 设置为 64,最多允许 1044 个同时进行的进程,这应该足以满足几乎所有的用途。但是,如果在试图启动另一个程序时显示错误,或者服务器在运行时有大量的并发用户,请增加数量并重新编译。

注意

maxusers 限制可以登录机器的用户数量。相反,考虑到系统中的最大用户数和每个用户将运行的进程数,它将各种表的大小设置为合理值。

注 2

自动调整算法将 maxusers 设定为等同系统中的内存量,最小为 32,最大为 384。

14.9.1.2. kern.ipc.soacceptqueue

sysctl(8) 变量 kern.ipc.soacceptqueue 限制了用于接受新 TCP 连接的监听队列的大小。默认值 128 通常太低,不利于稳健地处理高负荷的 web 服务器上的新连接。对于这样的环境,建议将这个值增加到 1024 或更高。像 sendmail(8) 或 Apache 这样的服务可能本身就限制了监听队列的大小,但通常在其配置文件中会有一个指令来调整队列大小。大的监听队列在避免拒绝服务(DoS)攻击方面更具优势。

14.9.2.网络优化

内核配置选项 NMBCLUSTERS 决定了系统可用的网络 Mbufs 的数量。一个大量使用的服务器,如果 Mbufs 的数量很低,会妨碍性能。每个簇代表大约 2K 的内存,所以 1024 的值代表 2 兆字节的内核内存保留给网络缓冲区。可以做一个简单的计算来计算出需要多少个。一个网络服务器的最大同时连接数为 1000,每个连接使用 6K 的接收和 16K 的发送缓冲区,需要大约 32MB 的网络缓冲区来覆盖网络服务器。一个好的经验法则是乘以 2,所以 2 x 32 MB / 2 KB = 64 MB / 2 kB = 32768。对于拥有更大内存的机器,建议使用 4096 和 32768 之间的值。千万不要为这个参数随意指定一个高的值,因为它可能导致启动时崩溃。要观察网络缓冲族的使用情况,可以使用 netstat(1) -m

应该使用可调参数 kern.ipc.nmbclusters 来在启动时进行优化。只有老版本的 FreeBSD 需要使用 NMBCLUSTERS 内核选项 config(8)

对于大量使用 sendfile(2) 系统调用的繁忙服务器,可能需要通过内核配置选项 NSFBUFS 或在 boot/loader.conf 中设置其值来增加 sendfile(2)冲区的数量 (详见 oader(8))。这个参数需要优化的一个常见指标是看到当进程处于 sfbufa 状态时。sysctl(8) 变量 kern.ipc.nsfbufs 是只读的。这个参数在名义上与 kern.maxusers 呈比例关系,但可能需要进行相应的调整。

重要

即使一个套接字被标记为非阻塞,在其上调用 sendfile(2) 时仍可能会导致 sendfile(2) 的调用阻塞,除非有足够的 struct sf_buf 可用。

14.9.2.1. net.inet.ip.portrange.*

sysctl(8) 变量 net.inet.ip.portrange.* 控制自动绑定到 TCP 和 UDP 套接字的端口号范围,其中有三个范围:低范围,默认范围和高范围。大多数网络程序使用默认范围,它由 net.inet.ip.portrange.firstnet.inet.ip.portrange.last 控制,它们的默认值分别为 1024 和 5000。绑定的端口范围用于出站连接,在某些情况下,系统有可能运行到端口之外。这种情况最常发生在运行一个高负荷的网络代理时。当运行一个主要处理传入连接的服务器,如 Web 服务器,或有有限数量的传出连接,如邮件中转时,端口范围不是问题。对于端口不足的情况,建议适度增加 net.inet.ip.portrange.last。10000、20000 或 30000 的数值可能是合理的。在改变端口范围时要考虑到防火墙的影响。一些防火墙可能会阻止大范围的端口,通常是低编号的端口,并希望系统使用较高范围的端口进行外发连接。出于这个原因,不建议降低 net.inet.ip.portrange.first 的值。

14.9.3.虚拟内存

14.9.3.1. kern.maxvnodes

虚拟节点(vnode)是一个文件或目录的内部存在形式。增加操作系统可用的虚拟节点的数量可以减少磁盘 I/O。通常情况下,这是由操作系统处理的,不需要改变。在某些情况下,磁盘 I/O 是一个瓶颈,系统正在耗尽虚拟节点,这时需要增加虚拟节点。非活跃和空闲的内存的数量需要被考虑在内。

要查看当前正在使用的虚拟节点的数量:

# sysctl vfs.numvnodes
vfs.numvnodes: 91349

查看虚拟节点的最大数量:

# sysctl kern.maxvnodes
kern.maxvnodes: 100000

如果当前的虚拟节点使用量接近最大值,可以尝试将 kern.maxvnodes 的数值增加到 1000。应密切关注 vfs.numvnodes 的数量,如果它再次攀升到最大值,将需要进一步增加 kern.maxvnodes。除此之外,top(1) 报告的内存的使用变化是可见的,并且应该有更多的内存处于活动状态。