前段时间同事让我帮忙查找一台web服务器上的apache的log出现大批报警的原因,经过努力终于把困扰了很久的问题找出来了,原来是应用维护人员修改了/etc/sysctl.conf里vm.overcommit_memory的值为2导致。

系统默认的相关值:

[root@webserver /root]
#sysctl -a|grep comm
vm.overcommit_ratio = 50
vm.overcommit_memory = 0

这台机器物理内存配置为8G,swap默认是2G.

当vm.overcommit_memory=2时,也就意味着真正可用的虚拟内存=(物理内存*vm.overcommit_ratio/100)+swap=6G。而JAVA分配了3G,但事实上确占用了3.7G的内存。再加上系统本身占用了一部份内存。apache采用worker模式(httpd.conf里定义最开始启动5个进程,而每个进程最多可启动64个线程),所以系统稍微有一些请求,就很容易出现如下情况:
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [notice] Apache configured — resuming normal operations
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread
[Wed Jul 22 17:53:55 2009] [alert] (12)Cannot allocate memory: apr_thread_create: unable to create worker thread

以下为kernel自带的官方说明:
The Linux kernel supports the following overcommit handling modes

0?? -?? Heuristic overcommit handling. Obvious overcommits of
address space are refused. Used for a typical system. It
ensures a seriously wild allocation fails while allowing
overcommit to reduce swap usage.? root is allowed to
allocate slighly more memory in this mode. This is the
default.

1?? -?? Always overcommit. Appropriate for some scientific
applications.

2?? -?? Don’t overcommit. The total address space commit
for the system is not permitted to exceed swap + a
configurable percentage (default is 50) of physical RAM.
Depending on the percentage you use, in most situations
this means a process will not be killed while accessing
pages but will receive errors on memory allocation as
appropriate.

The overcommit policy is set via the sysctl `vm.overcommit_memory’.

The overcommit percentage is set via `vm.overcommit_ratio’.

The current overcommit limit and amount committed are viewable in
/proc/meminfo as CommitLimit and Committed_AS respectively.

当vm.overcommit_memory设置为2的模式下,意味着当应用程序向系统请求分配(malloc)虚拟内存的时候,系统会分配给你一段address space,如果有新的应用程序请求分配内存时,系统也可能会把这段已分配的内存(但没真正使用)分配给新的应用程序。

CommitLimit: Based on the overcommit ratio (’vm.overcommit_ratio’),
this is the total amount of? memory currently available to
be allocated on the system. This limit is only adhered to
if strict overcommit accounting is enabled (mode 2 in
‘vm.overcommit_memory’).
The CommitLimit is calculated with the following formula:
CommitLimit = (’vm.overcommit_ratio’ * Physical RAM) + Swap
For example, on a system with 1G of physical RAM and 7G
of swap with a `vm.overcommit_ratio` of 30 it would
yield a CommitLimit of 7.3G.
For more details, see the memory overcommit documentation
in vm/overcommit-accounting.
Committed_AS: The amount of memory presently allocated on the system.
The committed memory is a sum of all of the memory which
has been allocated by processes, even if it has not been
“used” by them as of yet. A process which malloc()’s 1G
of memory, but only touches 300M of it will only show up
as using 300M of memory even if it has the address space
allocated for the entire 1G. This 1G is memory which has
been “committed” to by the VM and can be used at any time
by the allocating application. With strict overcommit
enabled on the system (mode 2 in ‘vm.overcommit_memory’),
allocations which would exceed the CommitLimit (detailed
above) will not be permitted.
This is useful if one needs
to guarantee that processes will not fail due to lack of
memory once that memory has been successfully allocated.