How to Setup Varnish 3.0 in Front of Nginx, PHP5.4 (PHP-FPM)

In the previous post, i have describes the steps to setup web server that running on Nginx and PHP5.4 (PHP-FPM). The setup and configuration work well with the WordPress site. This article will describe how to speed up the existing NGINX + PHP web server with one of the popular web accelerator called Varnish Cache, also known as caching HTTP reverse proxy. Varnish cache will speed up the website delivery to the visitor and reduce the CPU time, less database requests and file lookups. This steps to setup varnish has been tested on CentOS 6, CentOS 7, Oracle Linux 7 and RHEL 7.

Setup Varnish in front of Nginx

Varnish is a HTTP accelerator that can run side by side with either Apache or Nginx web server. In this tutorial, i will setup Varnish to run on port 80 while NGINX on port 8080.

Setup Varnish

Benefits of Varnish

1. Reduce server CPU load and time
2. Increase website load speed
3. Can handle large number of websites visitors
4. Varnish supports load balancing

How to Setup Varnish

1. Setup Nginx, PHP5.4 (PHP-FPM) as web server. Refer to this tutorial.

2. Install varnish :

[root@vps ~]# wget https://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm
[root@vps ~]# rpm -Uvh varnish-release-3.0-1.el6.noarch.rpm
[root@vps ~]# yum install varnish -y

3. Configure and setup Varnish :

Below configuration for /etc/sysconfig/varnish and /etc/varnish/default.vcl say that NGINX are running as the backend server on localhost at port 8080 while Varnish will run in front of it listening on port 80.

a. Modify /etc/sysconfig/varnish :

[root@vps ~]# vim /etc/sysconfig/varnish

Add the following. if your VPS running SSD disk, you can select varnish_storage as a cache method instead of memory (-s malloc) :

..
..
DAEMON_OPTS="-a :80 \
             -T localhost:6082 \
             -f /etc/varnish/default.vcl \
             -u varnish -g varnish \
             -S /etc/varnish/secret \
             -p thread_pool_add_delay=2 \
             -p thread_pools=2 \
             -p thread_pool_min=400 \
             -p thread_pool_max=4000 \
             -p session_linger=50 \
             -p sess_workspace=262144 \
             -s file,/var/lib/varnish/varnish_storage.bin,512m"
..
..
VARNISH_LISTEN_PORT=80
..
..

b. Modify /etc/varnish/default.vcl :

[root@vps ~]# vim /etc/varnish/default.vcl

Add as below :

backend default {
    .host = "127.0.0.1";
    .port = "8080";
    .connect_timeout = 600s;
    .first_byte_timeout = 600s;
    .between_bytes_timeout = 600s;
    .max_connections = 800;
}


acl purge {
	"127.0.0.1";
}

sub vcl_recv {


	# Allow purge requests
	if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
            error 405 "Not allowed.";
        }
        ban("req.url ~ ^" + req.url + " && req.http.host == " + req.http.host);
        return(lookup);
    }

	# Add header for sending client ip to backend
	set	req.http.X-Forwarded-For = client.ip;

	# Normalize	content-encoding
	if (req.http.Accept-Encoding) {
        if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
            remove req.http.Accept-Encoding;
        } elsif (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 cookies and query string for real static files
    if (req.url ~ "^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }

    # Don't cache admin
    if (req.url ~ "((wp-(login|admin|comments-post.php|cron.php))|login)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
        return (pass);
    } else {
    	unset req.http.cookie;
    }
}

sub vcl_hit {
	# purge cached objects from memory
	if (req.request == "PURGE") {
		purge;
		error 200 "Purged";
	}
}

sub vcl_miss {
	# purge cached objects varients from memory
	if (req.request == "PURGE") {
		purge;
		error 404 "Purged varients";
	}
}

sub vcl_fetch {
	# Dont cache admin
	if (req.url ~ "(wp-(login|admin|comments-post.php|cron.php))|login" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
    	    return (deliver);
	} else {
    	    if ( beresp.ttl > 0s ) {
    	        unset beresp.http.set-cookie;
    	    }
	}
}


sub vcl_deliver {

	# Remove unnecessary headers
	remove resp.http.Server;
	remove resp.http.X-Powered-By;
	remove resp.http.X-Varnish;
	remove resp.http.Via;

	# DIAGNOSTIC HEADERS
	if (obj.hits > 0) {
		set resp.http.X-Cache = "HIT";
	} else {
		set resp.http.X-Cache = "MISS";
	}

}

4. Reconfigure NGINX to work with Varnish :

a. Configure default.conf :

[root@vps ~]# vim /etc/nginx/conf.d/default.conf

Add the following :

..
server {
    listen       127.0.0.1:8080;
    server_name  localhost;
..

b. Configure common.conf :

[root@vps ~]# vim /etc/nginx/conf.d/common.conf
..
..

listen 127.0.0.1:8080;
..
..

c. Configure Vhost for domain example.com :

[root@vps ~]# vim /etc/nginx/sites-available/example.com.conf

Change listen to 127.0.0.1:8080; :

server {
listen       127.0.0.1:8080;
    server_name example.com;
    rewrite ^/(.*)$ http://www.example.com/$1 permanent;
}
..

5. Restart NGINX, php-fpm and Varnish :

[root@vps ~]# service nginx restart; service php-fpm restart; service varnish restart

6. Make sure NGINX listening to port 8080 and Varnish port 80 :

[root@vps ~]# netstat -plunt  | grep LISTEN
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      3119/varnishd
tcp        0      0 127.0.0.1:8080              0.0.0.0:*                   LISTEN      3065/nginx

Thats All.

How to Install Varnish Cache With Apache On CentOS 6.5

Varnish is an open source web accelerator (also called a HTTP reverse proxy) designed for content-heavy dynamic web sites to speed up web server’s performance. Typical Web server will handles all the request and returning a response to the client. But with Varnish cache, it will serve the saved copy page instead of re-requesting the same revisited page from web server. This will reduced the server load and increased the response times. For those who plan to run a virtual private server (VPS) and also run a dedicated web server, hope that this article will help. This article will describe how to install and configure Varnish Cache with Apache on CentOS 6.5.

1. Setup varnish repo :

[root@centos6 ~]# wget http://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm
[root@centos6 ~]# rpm --nosignature -i varnish-release-3.0-1.el6.noarch.rpm

2. Install Varnish and Apache :

[root@centos6 ~]# yum install varnish -y
[root@centos6 ~]# yum install httpd -y

3. Make both program start at boot :

[root@centos6 ~]# chkconfig --level 345 varnish on
[root@centos6 ~]# chkconfig --level 345 httpd on

4. Configure apache to listen to port 8080 :

[root@centos6 ~]# vi /etc/httpd/conf/httpd.conf

Modify below :

Listen 8080

5. Configuring Varnish Cache :

[root@centos6 ~]# vim /etc/sysconfig/varnish
..
..
# # Main configuration file. You probably want to change it :)
VARNISH_VCL_CONF=/etc/varnish/default.vcl
#
# # Default address and port to bind to
# # Blank address means all IPv4 and IPv6 interfaces, otherwise specify
# # a host name, an IPv4 dotted quad, or an IPv6 address in brackets.
# VARNISH_LISTEN_ADDRESS=
#VARNISH_LISTEN_PORT=6081
VARNISH_LISTEN_PORT=80
#
# # Telnet admin interface listen address and port
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
#
# # Shared secret file for admin interface
VARNISH_SECRET_FILE=/etc/varnish/secret
#
# # The minimum number of worker threads to start
VARNISH_MIN_THREADS=50
#
# # The Maximum number of worker threads to start
VARNISH_MAX_THREADS=1000
#
# # Idle timeout for worker threads
VARNISH_THREAD_TIMEOUT=120
#
# # Cache file location
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
#
# # Cache file size: in bytes, optionally using k / M / G / T suffix,
# # or in percentage of available disk space using the % suffix.
VARNISH_STORAGE_SIZE=1G
#
# # Backend storage specification
VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
#
# # Default TTL used when the backend does not specify one
VARNISH_TTL=120
#
# # DAEMON_OPTS is used by the init script.  If you add or remove options, make
# # sure you update this section, too.
DAEMON_OPTS="-a ${VARNISH_LISTEN_ADDRESS}:${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"
#
..
..

Add the following in /etc/varnish/default.vcl :

[root@centos6 ~]# vim /etc/varnish/default.vcl
backend default {
  .host = "127.0.0.1";
  .port = "8080";
}

6. Start Varnish and Apache ”

[root@centos6 ~]# service varnish start
Starting Varnish Cache:                                    [  OK  ]
[root@centos6 ~]# service httpd start
Starting httpd:                                            [  OK  ]

7. verify varnish and Apache running on the correct port :

[root@centos6 ~]# netstat -plunt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      1042/rpcbind
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      21729/varnishd
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1075/sshd
tcp        0      0 127.0.0.1:6082              0.0.0.0:*                   LISTEN      21728/varnishd
tcp        0      0 :::111                      :::*                        LISTEN      1042/rpcbind
tcp        0      0 :::80                       :::*                        LISTEN      21729/varnishd
tcp        0      0 :::8080                     :::*                        LISTEN      1182/httpd
tcp        0      0 :::22                       :::*                        LISTEN      1075/sshd
udp        0      0 0.0.0.0:111                 0.0.0.0:*                               1042/rpcbind
udp        0      0 0.0.0.0:793                 0.0.0.0:*                               1042/rpcbind
udp        0      0 :::111                      :::*                                    1042/rpcbind
udp        0      0 :::793                      :::*                                    1042/rpcbind

8. Verify the Varnish by running the following command.

[root@centos6 ~]# curl -I http://www.ehowstuff.local
HTTP/1.1 200 OK
Server: Apache/2.2.15 (CentOS)
X-Powered-By: PHP/5.3.3
X-Pingback: http://www.ehowstuff.local/xmlrpc.php
Content-Type: text/html; charset=UTF-8
Content-Length: 7990
Accept-Ranges: bytes
Date: Sun, 13 Apr 2014 15:41:41 GMT
X-Varnish: 1889373153
Age: 0
Via: 1.1 varnish
Connection: keep-alive

9. ApacheBench performance test without Varnish Cache

[root@centos6 ~]# ab -k -n 1000 -c 50 http://www.ehowstuff.local:8080/
This is ApacheBench, Version 2.3 < $Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.ehowstuff.local (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        Apache/2.2.15
Server Hostname:        www.ehowstuff.local
Server Port:            8080

Document Path:          /
Document Length:        0 bytes

Concurrency Level:      50
Time taken for tests:   217.545 seconds
Complete requests:      1000
Failed requests:        81
   (Connect: 0, Receive: 0, Length: 81, Exceptions: 0)
Write errors:           0
Non-2xx responses:      1000
Keep-Alive requests:    0
Total transferred:      318518 bytes
HTML transferred:       20331 bytes
Requests per second:    4.60 [#/sec] (mean)
Time per request:       10877.237 [ms] (mean)
Time per request:       217.545 [ms] (mean, across all concurrent requests)
Transfer rate:          1.43 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    3  12.1      0      65
Processing:   219 10822 17202.8   3275   61139
Waiting:      218 10802 17210.6   3228   61138
Total:        239 10825 17201.5   3275   61139

Percentage of the requests served within a certain time (ms)
  50%   3275
  66%   4513
  75%   5570
  80%  12099
  90%  40539
  95%  60069
  98%  60103
  99%  60200
 100%  61139 (longest request)

10. ApacheBench performance test with Varnish Cache

[root@centos6 ~]# ab -k -n 1000 -c 50 http://www.ehowstuff.local/
This is ApacheBench, Version 2.3 < $Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.ehowstuff.local (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        Apache/2.2.15
Server Hostname:        www.ehowstuff.local
Server Port:            80

Document Path:          /
Document Length:        7990 bytes

Concurrency Level:      50
Time taken for tests:   0.227 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    1000
Total transferred:      8565396 bytes
HTML transferred:       8221710 bytes
Requests per second:    4410.08 [#/sec] (mean)
Time per request:       11.338 [ms] (mean)
Time per request:       0.227 [ms] (mean, across all concurrent requests)
Transfer rate:          36888.79 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   3.2      0      19
Processing:     7   10   1.7     10      18
Waiting:        1    4   2.3      4      15
Total:          7   11   4.1     10      31

Percentage of the requests served within a certain time (ms)
  50%     10
  66%     10
  75%     11
  80%     11
  90%     12
  95%     13
  98%     27
  99%     31
 100%     31 (longest request)

11. Result on Steps (9) and (10) shows that Apache with Varnish serve faster response than running Apache standalone.