Figure 12-7. mod_proxy buffering
mod_perl streams the generated response into the kernel send buffer,
which in turn goes into the kernel receive buffer of mod_proxy via
the TCP/IP connection. mod_proxy then streams the file into the
kernel send buffer, and the data goes to the client over the TCP/IP
connection. There are four buffers between mod_perl and the client:
two kernel send buffers, one receive buffer, and finally the
mod_proxy user space buffer. Each of those buffers will take the data
from the previous stage, as long as the buffer is not full. Now
it's clear that in order to immediately release the
mod_perl process, the generated response should fit into these four
buffers.
If the data doesn't fit immediately into all
buffers, mod_perl will wait until the first kernel buffer is emptied
partially or completely (depending on the OS implementation) and then
place more data into it. mod_perl will repeat this process until the
last byte has been placed into the buffer.
The kernel's receive buffers
(recvbuf) and send buffers
(sendbuf) are used for different things: the
receive buffers are for TCP data that hasn't been
read by the application yet, and the send buffers are for application
data that hasn't been sent over the network yet. The
kernel buffers actually seem smaller than their declared size,
because not everything goes to actual TCP/IP data. For example, if
the size of the buffer is 64 KB, only about 55 KB or so can actually
be used for data. Of course, the overhead varies from OS to OS.
It might not be a very good idea to increase the
kernel's receive buffer too much, because you could
just as easily increase mod_proxy's user space
buffer size and get the same effect in terms of buffering capacity.
Kernel memory is pinned (not swappable), so
it's harder on the system to use a lot of it.
The user space buffer size for mod_proxy seems to be fixed at 8 KB,
but changing it is just a matter of replacing
HUGE_STRING_LEN with something else in
src/modules/proxy/proxy_http.c under the Apache
source distribution.
mod_proxy's receive buffer is configurable by the
ProxyReceiveBufferSize parameter. For example:
ProxyReceiveBufferSize 16384
will create a buffer 16 KB in size.
ProxyReceiveBufferSize must be bigger than or
equal to 512 bytes. If it's not set or is set to
0, the system default will be used. The number
it's set to should be an integral multiple of 512.
ProxyReceiveBufferSize cannot be bigger than the
kernel receive buffer size; if you set the value of
ProxyReceiveBufferSize larger than this size, the
default value will be used (a warning will be printed in this case by
mod_proxy).
You can modify the source code to adjust the size of the
server's internal read-write buffers by changing the
definition of IOBUFSIZE in
include/httpd.h.
Unfortunately, you cannot set the kernel buffers'
sizes as large as you might want because there is a limit to the
available physical memory and OSes have their own upper limits on the
possible buffer size. To increase the physical memory limits, you
have to add more RAM. You can change the OS limits as well, but these
procedures are very specific to OSes. Here are some of the OSes and
the procedures to increase their socket buffer sizes: