You are on right track. Here are some things which should help you figure out remaining details.
You need detailed monitoring of Apache on all stats provided by mod_status
- "_" Waiting for Connection
- "S" Starting up
- "R" Reading Request
- "W" Sending Reply
- "K" Keepalive (read)
- "D" DNS Lookup
- "C" Closing connection
- "L" Logging
- "G" Gracefully finishing
- "I" Idle cleanup of worker
- "." Open slot with no current process
Memory is always scarce, if you check all VM providers basically charge VM price based on
size of memory you get. So be mindful when you spend it.
You can define ServerLimit (needs apache stop/start to redefine) and then use MaxClients (which can be adjusted with restart) to set maximum value your server will be able to handle. These values are there to protect someone from internet to exhaust your servers resources. If you calculated you can have 13 threads; 13 it is.
See what is your usage pattern over some period of time and adjust StartServers to be at average usage. So you will start with something that is close to average usage; and if web server needs to serve more requests it will spin up few more workers. Volume of those will be controlled by ceil value of MaxClients and
- MinSpareServers
- MaxSpareServers
So you don't want to instantly spin up ton of workers if rise in your traffic is small; you would rather want to spin up worker or two to avoid wasting memory on bunch of additional workers that will probably not be used. It takes MaxRequestsPerChild
for spawned process to be destroyed and then based on usage Apache will decide if it needs to start new one to replace old worker.
Regarding MaxRequestsPerChild, you want to avoid 0 here; while it is a good idea to keep things cached in memory for performance, you don't have memory to spare for that. Having lower number something like 1000 or 2000 here is likely better option than default 10000 because recycling workers after serving less HTTP requests will limit their lifetime in which they gradually grow in terms of memory usage. So recycling these sooner rather than later will save you some memory.
As for user count; it depends... if your users are going to be hitting web server nicely throughout the day or is everyone going to need web server at the same time. You need to monitor (graphs and stuff) memory, apache, cpu usage and other system health figures and examine those when you try to come up with way to make things run smoother because there is no general recipe to make things better; it depends a lot on use case and usage patterns.
On memory usage of Apache, this is a tricky problem. Each Apache thread has access to certain portion of memory. This accessible address space is in one part unique to this particular process, whereas some other portions of address space are shared with other Apache threads. So when you want to calculate how much all of them use, you want to make sure you don't account for same address space twice.
Here is my approach to calculate Apache memory footprint; you will likely need to alter first line to fit process name of your Apache because depending on distribution some name Apache process 'httpd' some 'apache2' or possibly something else I can't think of right now...
cmd='httpd'
ps -o size=,rss=,vsz= $(pgrep "$cmd") | awk '
{ size_sum += $1; rss_sum += $2; vsz_sum += $3; processes += 1 }
END {
printf "Size : %.2f (%.2f) MB\n",size_sum/1024,size_sum/1024/processes
printf "RSS : %.2f (%.2f) MB\n",rss_sum/1024,rss_sum/1024/processes
printf "VSZ : %.2f (%.2f) MB\n",vsz_sum/1024,vsz_sum/1024/processes
}'
output should look like
Size : 178.84 (16.26) MB
RSS : 118.08 (10.73) MB
VSZ : 1754.29 (159.48) MB
This is from one of my web servers.
First value in each row is total, second in parentheses is per process avg.
To explain values, I'll quote ps man page
- Size : approximate amount of swap space that would be required if the process were to dirty all writable pages and then be swapped out. This number is very rough!
- RSS : resident set size, the non-swapped physical memory that a task has used
- VSZ : virtual memory size of the process
What this means for your maths is; processes can potentially grow to VSZ
size, they are currently using RSS
of RAM which is figure you want to use in your equation when trying to calculate MaxClients/ServerLimit and SIZE
is theoretically size your processes could take if completely swapped our due to being idle. Some sources on the topic advocate calculating memory footprint using pmap like
ps -ef | grep httpd | grep -v ^root | awk '{ print $2 '} | xargs pmap -d | grep ^mapped: | awk '{ print $4 }' | cut -dK -f1 | awk '{ SUM += $1} END { print SUM/NR }'
This should return same value as SIZE
we calculated earlier.