Nginx Image Filter Module is a fantastic module for serving resized images. Mu WordPress can use a lot of cpu’s and ram for image serving and this module can eliminate this problem. With this set up I was able to take my resized image serving up to 5000 requests per second. (2500 r/ps non cached, 5000 r/ps proxy cached)
As outlined in my other nginx image filter module post you need to implement the image at configuration time when you build nginx.
You have one nginx instance dedicated to image resizing and requests for image resizes get proxied to the nginx image serving instance from your main nginx server.
Resized images and cropped images are served like so:
Resize
http://subdomain.muinstall.com/ngimages/resize/files/2009/04/24879.jpg?w=120&h=120
Crop
http://subdomain.muinstall.com/ngimages/crop/files/2009/04/24879.jpg?w=120&h=120
You must include both w and h for width and height. If you miss either of these parameters you’ll get 415 errors.
Install Nginx Image Server:
sudo apt-get install libgd2-xpm-dev ./configure --prefix=/usr/local/nginx_images --with-http_image_filter_module make make install
Copy /etc/init.d/nginx /etc/init.d/nginx_images
Make changes to following lines on /etc/init.d/nginx_images.
DAEMON=/usr/local/nginx_images/sbin/$NAME PIDFILE=/usr/local/nginx_images/logs/$NAME.pid
Here is the config for the nginx image server (/usr/local/nginx_images/conf/nginx.conf):
user www-data;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format small '$body_bytes_sent $request_time $request_uri $args $status $uri';
sendfile on;
keepalive_timeout 65;
server {
listen 81;
server_name localhost;
access_log logs/host.access.log small;
location / {
root html;
index index.html index.htm;
}
location /crop/ {
set $width $arg_w;
set $height $arg_h;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:80;
image_filter crop $arg_w $arg_h;
error_page 415 = /empty;
}
location /resize/ {
set $width $arg_w;
set $height $arg_h;
### if we don't set proxy header as http_host the host is read a 127.0.0.1
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:80;
image_filter resize $arg_w $arg_h;
error_page 415 = /empty;
}
location = /empty {
empty_gif;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
Here is what you add to your main nginx mu install server conf:
location ~* ^.+\.(jpg|jpeg|gif|png|xml|ico|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js)$
{
access_log /usr/local/nginx/logs/statics.access.log small;
root /home/mu/public_html;
if ($request_uri ~* "/ngimages" ) {
error_page 404 = @ngimages;
}
rewrite ^/resize/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
rewrite ^/crop/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
rewrite ^/files(/.*)$ /wp-content/blogs.dir/$host/files$1 last;
break;
}
location @ngimages {
access_log /usr/local/nginx/logs/ngimages.access.log small;
proxy_read_timeout 10;
proxy_cache_key $host$request_uri$args;
proxy_cache_valid 200 304 7d;
proxy_cache_valid 301 302 1h;
proxy_cache_valid 404 403 402 401 504 502 20m;
proxy_cache_valid any 1m;
proxy_cache two;
proxy_set_header Host $http_host;
rewrite ^/ngimages/(.*) /$1 break;
proxy_pass http://127.0.0.1:81;
}
wp-config at the bottom after abs path define and before require wp-settings:
if ( !defined('ABSPATH') )
define('ABSPATH', dirname(__FILE__) . '/');
if ( !defined('WP_CONTENT_DIR') )
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
if( !defined( "UPLOADBLOGSDIR" ) )
define( "UPLOADBLOGSDIR", 'wp-content/blogs.dir' );
if( !defined( "UPLOADS" ) )
define( "UPLOADS", UPLOADBLOGSDIR . "/{$_SERVER['HTTP_HOST']}/files/" );
if( !defined( "BLOGUPLOADDIR" ) )
define( "BLOGUPLOADDIR", WP_CONTENT_DIR . "/blogs.dir/{$_SERVER['HTTP_HOST']}/files/" );
One Comment
Just wanted to tell you that you can do the same by using proxy_store instead of proxy_cache. Mirroring instead of caching – which might be a better option in some cases:
Might need some further editing for MU, I’ve only tested it with plain wordpress 2.9.
I’ve been running out of worker processes for the resizing nginx on a busy site, still looking into that:
2010/06/22 17:06:40 [alert] 56986#0: 8192 worker_connections are not enough.
Also, check out the constant WPMU_ACCEL_REDIRECT in wp-config.php (you have to add it if it’s missing.
If you set it to true, blogs.php uses X-Accel-Redirect instead of readfile() to serve the file. Offloads the work from PHP to nginx.