Sunday, June 24, 2018

Nginx Content Caching


Introduction
------------

- if caching is enabled, Nginx saves responses to disk cache and uses them to
  respond to clients w/o having to proxy requests for the same content every
  time

Enabling Caching Response
-------------------------

enables caching
http {
    ...
    proxy_cache_path /data/nginx/cache keys_zone=one:10m;
      # - /data/nginx/cache -> cache location
      # - keys_zone -> name of shared memory zone
      # - 10m -> size of shared memory zone; doesn't limit the
      #          total amount of cached response data
      # `proxy_cache_path` must be within ttp context level

    server {
        proxy_cache one;
          # - this tells the context to cache reponses using
          #   key_zone=one settings

        location / {
            proxy_pass http://localhost:8000;
        }
    }
}
limits amount of
cached response
data
proxy_cache_path .. max_size ??; 
  # note: this limit can be temporarily exceeded

How Nginx caches data
---------------------

Processes involved:

  1. cache manager
       - activated periodically to check cache state
       - if cached data exceeds `max_size`, cache manager removes the least
         accesed data

  2. cache loader
       - runs only once (after nginx starts)
       - loads metadata about previously cached data into share memory zone
       - loading cache at startup may slow down nginx during first few minutes
       - to avoid that, configure iterative loading by adding the followingin
         `proxy_cache_path`
           a. loader_treshold - iteration duration on milliseconds
                                (default: 200)
           b. loader_files - max items loaded per iteration (default: 100)
           c. loader_sleeps - delay between iteration in milliseconds
                              (default: 50)

The following setting has iteration which lasts 300 ms
or until 200 items have been loaded:

proxy_cache_path /data/nginx/cache keys_zone=one:10m loader_threshold=300 loader_files=200;

Specifying which requests to cache
----------------------------------

- by default, Nginx cache all reponses (received from proxied server) to HTTP
  GET and HEAD requests
- requests and cached responses have key identifiers
- if a request has same key as the cached responsed, Nginx sends the cached
  response to the client
- http, server, and location contexts can be controlled on what responses to
  cache

changes the request characteristics
used in calculating the key
proxy_cache_key "$host$request_uri$cookie_user";
defines the minimum number of times
that a request with the same key
must be made before the response
is cached
proxy_cache_min_uses 5;
cache responses to requests with
methods other than GET and HEAD
proxy_cache_methods GET HEAD POST;


Limiting/Bypassing Caching
--------------------------

- by default, responses remain in cache indefinitely
- they are only removed when:
    a. exceeds max configured size
    b. in order of time since last requested
- cached responses can be set on how long they can be valid by including in any
  of these contexts:
    a. http
    b. server
    c. location
- caching can by bypassed

way of limiting cache validity
proxy_cache_valid 200 302 10m;
  # responses w/ code 300/302 are valid for 10 minutes

proxy_cache_valid 404      1m;
  # responses w/ code 404 are valid for 1 minute

proxy_cache_valid any 5m;
  # any response are valid only for 5 minutes
bypasses caching when specific
condition(s) is/are met
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
  # if atleast 1 parameter is not empty, Nginx sends requests to
  # proxied server
bypasses caching entirely
proxy_no_cache $http_pragma $http_authorization;

Purging Cache
-------------

- outdated cache files can be removed
- necessary to prevent sending old and new versions of web pages at the same
  time
- cache is purged by receiving a special "purge" request

Configuring cache purge
1. On the http level, create a new variable, for example, $purge_method,
   that will depend on the $request_method variable:

http {
...
map $request_method $purge_method {
PURGE 1;
default 0;
}
}

2. In the location where caching is configured, include the proxy_cache_purge
   directive that will specify a condition of a cache purge request. In our
   example, it is the $purge_method configured at the previous step:

server {
listen      80;
server_name www.example.com;

location / {
proxy_pass  https://localhost:8002;
proxy_cache mycache;

proxy_cache_purge $purge_method;
}
}
Sending purge command
# When cache is enabled, you can send purge command by:

$ curl -X PURGE -D – "https://www.example.com/*"
HTTP/1.1 204 No Content
Server: nginx/1.5.7
Date: Sat, 01 Dec 2015 16:33:04 GMT
Connection: keep-alive

# - resources that have a common URL part (specified by the asterisk wildcard) will be removed
# - However, such cache entries will not be removed completely from the cache: they will remain
# - on the disk until they are deleted for either inactivity (the inactive parameter of
# - proxy_cache_path), or processed by the cache purger process, or a client attempts to access them.
Restricting access to
purge command
geo $purge_allowed {
   default         0;  # deny from other
   10.0.0.1        1;  # allow from localhost
   192.168.0.0/24  1;  # allow from 10.0.0.0/24
}

map $request_method $purge_method {
   PURGE   $purge_allowed;
   default 0;
}
Removes files completely
from cache
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=mycache:10m purger=on;
  # `purger=on` removes cache that matches an asterisk

Byte-Range Caching
------------------

- initial cache fill operation may take some time on large files
- when 1st request starts downloading a part of a video file, next requests will
  have to wait for the entire file to be downloaded and put into cache
- Nginx can cache range requests by using "cache slice module"
- Nginx must be compiled with "slice" module to work

Enables Byte-Range caching
1. Make sure your NGINX is compiled with the slice module.

2. Specify the size of the slice with the slice directive:
location / {
slice  1m;
}

   The slice size should be adjusted reasonably enough to make
   slice download fast. A too small size may result in excessive
   memory usage and a large number of opened file descriptors
   while processing the request, a too large value may result
   in latency.

3. Include the $slice_range variable to the cache key:
proxy_cache_key $uri$is_args$args$slice_range;

4. Enable caching of responses with 206 status code:
proxy_cache_valid 200 206 1h;

5. Enable passing range requests to the proxied server by
   passing the $slice_range variable in the Range header field:
proxy_set_header  Range $slice_range;
Example config
location / {
    slice             1m;
    proxy_cache       cache;
    proxy_cache_key   $uri$is_args$args$slice_range;
    proxy_set_header  Range $slice_range;
    proxy_cache_valid 200 206 1h;
    proxy_pass        http://localhost:8000;
}

No comments:

Post a Comment