Massively Scalable Content Caching with NGINX
By: Shamoda Jayasekara
Tags: Caching, Nginx

So, this is the example scenario we gonna implement now.

We have our 1st NGINX server listening on port 8000 and it serves a simple web page to the user. We have another NGINX server listening on port 80 and it points to the 1st server via an upstream. So, all the user requests that are coming to the 2nd server or to port 80 will be pointed to the upstream then it will forward those requests to the 1st server which is listing on port 8000. In that case, again user will get the exact same web page as the response.

These are the initial configurations of the two servers.

#################### 1st Server #######################

server {

listen 8000;

root /var/www/html;

index index.html;

server_name _;

location / {

try_files $uri $uri/ =404;

}

} ################## Upstream ##########################

upstream upstream_server {

server 127.0.0.1:8000;

} ################# 2nd Server ###########################

server {

listen 80;

location / {

include proxy_params;

proxy_pass http://upstream_server;

}

}

Once we hit port 80 with the initial configurations, we will get the following set of response headers, and you can see we do not have any caching-related headers in the set.

Okay, now we are going to implement the caching mechanism in our 2nd server level which is listening on port 80. So that it will serve the cached content or the cached web page to the user without forwarding the request to the 1st server which has the actual web page.

These are the new configurations for the 2nd server.

################## Cache Zone ######################### proxy_cache_path /var/cache/nginx

keys_zone=MyCache:10m

levels=1:2

inactive=60m

max_size=20g; ################## Upstream ##########################

upstream upstream_server {

server 127.0.0.1:8000;

} ################# 2nd Server ###########################

server {

listen 80;

location / {

include proxy_params;

proxy_pass http://upstream_server;

proxy_cache MyCache;

proxy_cache_valid any 10m;

add_header X-Proxy-Cache $upstream_cache_status;

}

}

Okay, let's take newly added configuration lines one by one.

################## Cache Zone ######################### proxy_cache_path /var/cache/nginx

keys_zone=MyCache:10m

levels=1:2

inactive=60m

max_size=20g;

We can define a location in the file system to store our cache and a shared memory space to store active keys with response metadata using proxy_cache_path directive. In this case, our cached responses will be stored in /var/cache/nginx , if the location does not exist NGINX will automatically create it for you. The active key name of the cache will be MyCache with 10MB of memory.

The levels parameter defines how the file structure should be created. It can have a maximum of 3 colon-separated levels. NGINX will create the cache base on the cache key which is a hashed string. Then it will store it in the provided file structure using the cache key as the file path. NGINX will break the subdirectories of the cache based on the value of the levels parameter.

The inactive parameter defines the time duration that NGINX will host the cache from its last use. After that inactive time period, NGINX will release the cache from the memory.

With the max_size directive we can specify the maximum cache size we want to keep in the configured location which is /var/cache/nginx . From that location, NGINX will load the cache keys into the shared memory space (MyCache).

Well, that’s about the proxy_cache_path directive and its parameters. Now let’s take a look at the server context.

################# 2nd Server ###########################

server {

listen 80;

location / {

include proxy_params;

proxy_pass http://upstream_server;

proxy_cache MyCache;

proxy_cache_valid any 10m;

add_header X-Proxy-Cache $upstream_cache_status;

}

}