WordPress Performance Guide : From 5 to 6100 requests/sec on a 1Vcpu/1GB Ram VPS

Fast Caching frontend

This is were Varnish-cache comes into place.
Varnish is a well known HTTP accelerator and a fabulous caching system. It is known to be widely used by Facebook, Paas Platform Heroku and many others.
However, Varnish has many drawbacks, including :

  • Full configuration is very complex and should be totally adapted to the code of the web application
  • It is quite impossible to make a single Varnish instance work with more than one webapp code (No WordPress + Magento on the same frontend)
  • An error in your configuration file could kill your performance or even worse makes you cache logged user traffic which could be terrible if done on an eCommerce software

However, Varnish has a well documented and extendable configuration (can even take Inline C!), is really easy to implement with WordPress, and will make our WordPress just fly.

I’ll pass on explaining the whole varnish configuration, as some is very complex. I’ll do a special paper about Varnish configuration. In the meantime, you can have a look here, here and there.

So first install varnish :

apt-get install varnish

Then edit the starting options, bind it to the port 80 and make some subsequent adjustment. Still on Debian, /etc/default/varnish.

DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -S /etc/varnish/secret \
             -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G \
             -p thread_pools=1 \
             -p thread_pool_min=100 \
             -p thread_pool_max=2000 \
             -p thread_pool_add_delay=2 \
             -p cli_timeout=10 \
             -p session_linger=100 \
             -p lru_interval=20"

Then there is the configuration file I specialy crafted for WordPress. Edit /etc/varnish/default.vcl


backend local {

	#Make it through nginx ( Internet ===> Varnish:80 ===> Nginx:8081 ===> Apache:8080 )
	.host = "127.0.0.1";
	.port = "8081";
}

sub vcl_recv {

	# Rules for all requests
	# Only the blog URL is cached
	if (req.http.host ~ "(blog\.brigato\.fr)") { set req.backend = local; }
	else { return (pass); }

	# Compatiblity with Apache log
	remove req.http.X-Forwarded-For;
	set req.http.X-Forwarded-For = client.ip;

	# Post requests will not be cached
	if (req.request == "POST") {
	return (pass);
	}

	# Normalize encoding/compression
	if (req.http.Accept-Encoding) {
		if (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip";	}
		elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; }
		else { remove req.http.Accept-Encoding; }
	}

	# Remove has_js and Google Analytics __* cookies.
	if (req.http.cookie) {
		set req.http.Cookie = regsuball(req.http.Cookie, "(^|;\s*)(__[a-z]+|has_js)=[^;]*", "");

		# Remove a ";" prefix, if present.
		set req.http.Cookie = regsub(req.http.Cookie, "^;\s*", "");

		# Remove empty cookies.
		if (req.http.Cookie ~ "^\s*$") {
		unset req.http.Cookie;
		}
	}

	# Serve the page
	unset req.http.vary;

	# If I am logged in to wordpress, I DO NOT WANT TO SEE cached pages
	if ( req.url ~ "^/wp-(login|admin)" || req.http.Cookie ~ "wordpress_logged_in_" ) {
		return (pass);
		} else {

		# If I'm just a regular visitor
		# If the request is static
		if (req.url ~ "\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)$") {
			# Remove the cookie and make the request static
			unset req.http.cookie;
			return (lookup);
		}

		# Try to lookup in the cache
		return (lookup);
	}

	# Cookie ? Not cacheable by default
	if (req.http.Authorization || req.http.Cookie) {
		return (pass);
	}

	# if host header is empty return 404
	error 404 req.http.host;
	return (lookup);
}

sub vcl_fetch {
	if (req.http.host ~ "(blog\.brigato\.fr)") {

		# Do not cache POST requests
		if (req.request == "POST") {
			return (pass);
		}

		# If the request is static
		if (req.url ~ "\.(jpeg|jpg|png|gif|ico|js|css|txt|gz|zip|lzma|bz2|tgz|tbz|html|htm)$") {
			# Cache it, and make it last 2 hours
			set beresp.ttl = 7200s;
			# Make the request static by removing any cookies set by those static files
			unset beresp.http.set-cookie;
			# Deliver the cached object
			return (deliver);
		}

		# If I am logged in to wordpress, I DO NOT WANT TO SEE cached pages
		if (req.http.cookie ~ "wordpress_logged_in") {
			return (pass);
		} else {

		# Cache anything for 2 minutes. When the cache expires it will be cached again and again, at the time of the request
			set beresp.ttl = 120s;
			return (deliver);
		}
	}
}

sub vcl_deliver {
	# Secure the header
	remove resp.http.Via;
	remove resp.http.X-Varnish;
	remove resp.http.Server;
	remove resp.http.X-Powered-By;
}

Remember to set theses lines according to your needs :

backend local {

	#Make it through nginx ( Internet ===> Varnish:80 ===> Nginx:8081 ===> Apache:8080 )
	.host = "127.0.0.1";
	.port = "8081";
}
[...]
	# Rules for all requests
	# Only the blog URL is cached
	if (req.http.host ~ "(blog\.brigato\.fr)") { set req.backend = local; }
[...]
sub vcl_fetch {
	if (req.http.host ~ "(blog\.brigato\.fr)") {

Then restart the varnish cache frontend.

/etc/init.d/varnish restart

At this time, you should obtain a Huge boost on performance. For me, it was 2700 requests/sec, as in my last post.

However this is still not good, as I knew thanks to further tests that Varnish was able to push more than 5000 requests/sec for static cached content.
Here is the trick : Remember to active KeepAlive Requests in Apache frontend. This was not activated under my Debian Installation.

Edit /etc/apache2/apache2.conf, look for KeepAlive lines, and adjust them :

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15

Then restart apache a last time.

/etc/init.d/apache2 restart

2 thoughts on “WordPress Performance Guide : From 5 to 6100 requests/sec on a 1Vcpu/1GB Ram VPS

  1. I’m using Varnish too now, and I like the 1000-2000 hits/s that it can easily provide on my low-end VPS. I do find you need quite a lot of RAM for it to work well, though!

  2. Pingback: WordPress Optimization Tips - Gabfire Premium WordPress Themes

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>