I fired up a fresh virtual machine (with SSD backed storage) and installed nginx on it. And then I wrote a script to generate a huge number of files, each containing a single server
block. They looked a lot like this:
[root@localhost ~]# cat /etc/nginx/sites/server047393.conf
server {
listen 80;
listen [::]:80;
server_name server047393;
}
At first I made 50,000 of them, but that only took 9 seconds to reload nginx, so then I moved up to 100,000. With that, it was consistently taking 20 seconds to reload nginx. About the first half of that time was disk I/O wait, the latter half was CPU. With this number of server blocks, nginx is using nearly 1GiB of RAM.
This really doesn't look like a problem, unless you have the nginx configuration on a really slow disk. It does get re-read in its entirety when you reload or restart nginx. With a rotational disk, this easily could take a couple of minutes to reload. Use an SSD or even a RAM disk to store the nginx configuration.
Indeed, nginx's own optimization advice for server names hardly mentions configuration parsing time. It's not really something you should care about very much. What it does talk about a lot is the amount of time it takes to locate the correct server
block to process an incoming request. By default nginx tries to optimize this to minimize CPU cache line misses.
To optimize this for your larger number of server names, you might need to do nothing, but you probably do need to adjust the server_names_hash_max_size
directive. Run nginx -t
. If you see a message like this:
nginx: [warn] could not build optimal server_names_hash, you should increase either server_names_hash_max_size: 512 or server_names_hash_bucket_size: 64; ignoring server_names_hash_bucket_size
Then you should tune server_names_hash_max_size
. Start by setting this to a power of two larger than the number of server_name
s you are creating. If you have 30,000 server names, start with server_names_hash_max_size 32768
.
The optimization document does mention that:
if nginx’s start time is unacceptably long, try to increase server_names_hash_bucket_size
.
I found in testing that this didn't really help, but if you want to try it, increase it by powers of two each time. This value must be a power of two, or nginx will not start. This value is set by default according to the CPU cache line size, so if you're on a virtual machine and the CPU properties are not correctly exposed to the VM, you might be able to safely double this number (or nginx refused to start in the first place, but that's a slightly different error message, could not build the server_names_hash
). Don't go overboard with it, or your incoming requests will be slowed down by CPU cache misses.