Apache HTTP服务器 2.0版本
描述符, 通常也成为文件句柄,
是一个程序用于读写打开的文件,或者打开网络插座以及其他各种设备的对象,
其表现形式是一个整数,大家熟知的stdin
, stdout
和
stderr
的描述符分别是 0, 1和2。
在Apache中,每个日志文件都占用一个描述符,
每个监听的网络插座又需要一个描述符,另外还有其他的一些。
Apache所使用的库文件也需要描述符。标准程序并不会打开许多描述符,
因此如果运行Apache使用了许多描述符(即, 有许多虚拟主机),
则可能会遇到一些潜在的问题。
操作系统对一个程序可以同时打开的描述符的数量是有限制的。 通常,限制包括三个方面。其一是内核限制,根据操作系统的不同, 或许可以调高此描述符数量(常称为FD_SETSIZE), 否则,就只能受限于一个(相对)小的数量。其二是所谓硬资源限制, 有些是由root在一个晦涩的操作系统文件中设置的,但常与内核限制相同。 其三是所谓软资源限制,它总是小于或等于硬限制, 比如,硬限制是1024,而软限制只有64。 任何用户都可以提高软限制,最高达到硬限制。 Root可以提高硬限制,最高达到系统最大值。 软限制是一个进程可以打开文件的最大数量的实际限制值。
总结:
#open files <= soft limit <= hard limit <= kernel limit
用limit
(csh)或ulimit
(sh)命令可以控制软硬限制。
更多信息见相应的man手册。比如,
可以用ulimit -n unlimited
来提高软限制到硬限制的值。
此命令应该包含在启动网站服务器的shell脚本中。
不幸的是,事情并不总是这么简单。正如上述, 你可能会遇到某些系统限制,而必须采取某些措施。 从1.2.1版本起,情况有所改善。以下是一部分系统及其相应措施的列表 (假设你使用的是1.2.1或更新的版本).
在BSDI 2.0 中,可以在EXTRA_CFLAGS
中增加-DFD_SETSIZE=nnn
(其中nnn是需要支持的描述符的数量,它必须小于硬限制)并编译Apache,以支持更多的描述符。
但是,这样处理在使用的Listen指令多于大约240个的时候会有些麻烦,
设置较高的FD_SETSIZE并重新编译内核可能可以解决这个问题。
类似于BSDI 2.0, 应该定义FD_SETSIZE
并重新编译,但是Listen的使用不受限制了。
Linux对每个进程可以打开的描述符有最大值为256的内核限制。 对2.0.x系列,在the Linux Information HQ的"unofficial patches"中, 有几个补丁可以提高这个限制到1024乃至更多, 但是这些补丁都不完美,而且在2.1.x中已经采取了思路大致相同的改进。 使用这些补丁会在编译所有程序时都提高FD_SETSIZE,除非重新编译所有的库。 执行其他程序时应该避免描述符的软限制大于256, 因此不要过分倚重这些提高描述符限制的补丁,以免给专职网站服务器带来麻烦。
Solaris的内核硬限制是1024 (在早期版本可能更低)。
但是使用stdio库的文件有不能多于255的描述符限制。
Apache的ErrorLog指令使用了stdio库,当虚拟主机的数量达到大约110个时
(每个有一个出错日志和一个访问日志),则必须在EXTRA_CFLAGS
中增加
-DHIGH_SLACK_LINE=256
并重新编译Apache,
而且,应该把出错日志数量控制在大约240个以内。
AIX 3.2?? 版本的硬限制似乎是128,而在4.1.5 版本中硬限制是2000。
修改/etc/conf/cf.d/stune
文件
或使用/etc/conf/cf.d/configure
的选项7 (用户和组的配置),
并修改内核参数NOFILES
到一个合理的较高的值。
SCO 推荐值在60 和11000之间, 默认值是110。
重新连接并重新启动,使新的描述符数量有效。
open_max_soft
和open_max_hard
到4096。
参阅sysconfig, sysconfigdb, 和sysconfigtab的说明。max-vnodes
到一个大于apache进程数*4096的值
(设置为250,000 对多数人都不错的)。参阅sysconfig, sysconfigdb, 和sysconfigtab的说明。NO_SLACK
可以回避OS中的一个错误。
CFLAGS="-DNO_SLACK" ./configure
有关其他操作系统的信息,可以提交到我们的Bug Report Page。
除了上述提到的,Apache使用的许多库也有些问题。 最常见的问题是,几乎为所有unix使用的DNS解析库中的绑定(bind), 在描述符大于256时会执行失败。我们怀疑其他库也存在类似的限制。 所以,1.2.1的代码采取了一种自卫的姿态, 试图保存小于16的描述符以备在处理每个请求时使用, 这称为low slack line。
注意,这应该是不会浪费描述符的,在接近极限时, Apache需要而又不能获得大于16的描述符,就会使用小于16的描述符。
在极端情况下,你可能希望降低low slack line, 但其实不应该这样做。
比如,在Solaris和BSDI 2.0 中这样做可以提高上述的240的限制,
但这只能在与处理请求所需描述符之间求得一个脆弱的平衡。
如果真要这样做,编译时的参数是LOW_SLACK_LINE
,
在httpd.h
头文件中也有个极为简单的说明。
最后,如果你怀疑你的问题就是slack引起的,则可以禁用它,
在EXTRA_CFLAGS
增加-DNO_SLACK
后重新编译,
并将你的情况提交到Bug
Report Page,以便我们研究。