[pmwiki-users] Extremely fast static page cache with nginx
Ed W
lists at wildgooses.com
Mon Mar 16 07:51:32 CDT 2015
Hi, I have had some success using recent Nginx's feature to do fastcgi
output caching. I don't have capacity to write up on the wiki neatly,
but I wonder if someone would like to repro this and writeup?
Essentially recent Nginx has a feature to cache proxied fastcgi output.
Actually it's had that feature for a long time, however, only recently
it introduced "If-Modified-Since" support to the caching. This means
that if you have a working pmwiki which is setup to correctly use IMS,
then you can trivially turn on nginx caching which captures the full
rendered HTML and saves/serves it from disk automatically. It will
check upstream IMS on each page fetch, so updates will be immediately
noticed (additionally you could play with the Expires header to prevent
this check and get even more speed)
For me this brings page render time down from 300-600ms to 5-6ms (which
is roughly my ping time to my server).
The rough overview of my setup is:
- I have my server definitions in /etc/nginx/vhost.d
- Various standard config definitions live in /etc/nginx, eg setup of
ruby or php environments, standard SSL params, standard gzip params, etc.
- I include cache.conf into nginx.conf
- I have a vhost definition in vhost.d which sets up the server, logging
details, etc and then includes std_pmwiki.conf to do the work
- Note my wiki php lives in $HTMLROOT/w/ there is no reason you couldn't
put the files somewhere else, including in the root directory
- Be careful with nginx to avoid executing php code which can be
uploaded by the user. I recommend specific location entries which
redirect desired scripts to some virtual location. The virtual location
redirects to execute the PHP environment. This is NOT how it's done
below... This is an older config that I haven't updated yet.
- So in the location where we execute the PHP code it's relatively
straightforward to turn on cgi caching. We must forcibly ignore the
Cache-Control and Expires headers since they request no caching (Note, I
disagree that the correct headers are returned by pmwiki?). Also we make
some exceptions to bypass caching under certain circumstances, eg we
only cache non logged in users, doing GET/HEAD requests
- Not shown here, but ideally we should examine the url parameters and
consider not caching certain request types. However, this can probably
be done more cleanly by being more selective about ignoring the
Cache-Control headers from pmwiki and moving such logic upstream? (eg
look at Cache-Control: no-store ?)
Nginx will automatically build an html store for you. Nginx must be
compiled with the cache feature. You can expire the cache in various
ways, including "rm -rf". Here I also set a reasonably short html cache
expiry time (few days) to avoid very stale pages being delivered if I
overlooked something.
I quite like this solution because it moves the intelligence upstream
into pmwiki. Improvements in caching in pmwiki automatically flow down
to us here.
Any comments? (Apologies for sketchy writeup and mishmash of tabs/spaces
in the config below)
Ed W
-------------------
# cat /etc/nginx/cache.conf
# Setup caching for pmwiki (and others?)
fastcgi_cache_path /var/www/cache/fastcgi levels=1:2 keys_zone=fastcgi:8m max_size=100m inactive=600m;
fastcgi_temp_path /var/www/cache/tmp;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
-------------------
# cat /etc/nginx/std_pmwiki.conf
rewrite ^/$ /w/pmwiki.php last;
rewrite ^/sitemap.xml$ /w/pmwiki.php?action=sitemap last;
location /w/pub/ {
# serve static files that exist without running other rewrite tests
if (-f $request_filename) {
expires 7d;
break;
}
}
location /w/uploads/ {
# serve static files that exist without running other rewrite tests
if (-f $request_filename) {
expires 2d;
break;
}
}
location / {
if (!-e $request_filename) {
rewrite ^/+([^\./]+(/[^\./]*)?)$ /w/pmwiki.php?n=$1 last;
}
}
location ~ /w/pmwiki\.php$ {
include /etc/nginx/fastcgi.conf;
fastcgi_pass 127.0.0.1:9000;
# caching
set $no_cache 0;
# Don't cache logged in users
if ($http_cookie ~ (PHPSESSID*)) {
set $no_cache 1;
}
# if ($query_string ~ "action=") {
# set $no_cache 1;
# }
fastcgi_cache_bypass $no_cache;
fastcgi_no_cache $no_cache;
fastcgi_cache fastcgi;
fastcgi_cache_methods GET HEAD;
fastcgi_cache_valid 2880m;
fastcgi_cache_revalidate on;
fastcgi_ignore_headers Cache-Control Expires;
add_header X-Cache-Status $upstream_cache_status;
}
location /w/ {
# unless rewritten to the php script then you get a 403 Forbidden
deny all;
}
More information about the pmwiki-users
mailing list