[Solved] LiteSpeed Cache + Joomla

webizen

Well-Known Member
#1
Joomla is a fairly populate content management system (CMS). It is a common sense that most Web sites have content that does not change frequently should use caching techniques to reduce load to server and improve end user experience. Joomla itself has three levels of caching:

1. Page caching
2. View caching
3. Module caching

Page caching is the one that significantly improves performance (8 times faster). However, the cache result (in html format) is saved as a php file in docroot/cache/page directory. IOW, php is still invoked to serve these pages.

LiteSpeed Caching

LiteSpeed webserver (LSWS) cache bypasses php invocation and serves cached page directly from LSWS cache. Hence a much bigger performance improvement can be achieved.

To work with Joomla (cached for guest visitor only), LSWS cache relies on a cookie token to differentiate whether a user is logged in or not. However, Joomla assigns cookie to any user (guest and logged in). cookie value changes as same session go through different stage (such as before login, after login, logout and log back in, etc) while cookie key stays the same. The easy way is the create desired cookie in joomla by modifying its code (small modification in login/logout stage). Login/Logout functions are located in the standard user component (docroot/component/com_user/controller.php).

The modification is as follows:
Code:
function login() {
                if(!JError::isError($error))
                {
                        // Redirect if the return url is not registration or login
                        if ( ! $return ) {
                                $return = 'index.php?option=com_user';
                        }
                        setcookie("loginuser","yes");     //  <==== add this line  # add "loginuser=yes" cookie upon successful login
                       $mainframe->redirect( $return );
Code:
function logout ()
                if(!JError::isError($error))
                {
                        setcookie("loginuser", "", time()-86400*365);  // <=== add this line # drop "loginuser" cookie upon logout.
                        if ($return = JRequest::getVar('return', '', 'method', 'base64')) {
                                $return = base64_decode($return);
                                if (!JURI::isInternal($return)) {
                                        $return = '';
                                }
                        }
Once test ok, implement rewrite rules to enable LSWS cache for the resources that required caching.

In file joomla_docroot/.htaccess
Code:
########## Begin - Joomla! core SEF Section
#
RewriteRule p.php - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule (.*) index.php 
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
#
########## End - Joomla! core SEF Section
Change to

Code:
########## Begin - Joomla! core SEF Section
#
RewriteRule p.php - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule (.*) index.php 
#### There is no need for this ENV
#RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
#
########## End - Joomla! core SEF Section

########## Begin - Rules for LSWS cache
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
RewriteCond %{HTTP_COOKIE} !loginuser
RewriteCond %{ORG_REQ_URI} !^/index.php$
RewriteCond %{ORG_REQ_URI} !^/administrator/
RewriteCond %{ORG_REQ_URI} (\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule .* - [E=Cache-Control:max-age=300,L]
########## End - Rules for LSWS cache
Explanation of the added rules:
1. Only cache for Head or Get requests
2. Cache for guest user (no loginuser cookie)
3. Cache request to any URLs like ((\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$) but excluding /index.php, and /administrator/*
4. Cache for 300 seconds

Note:
1. Joomla's login form (index.php) is not cache friendly (contain a security token) and has to be excluded from being cached.
2. /administrator/* is the Joomla backend. No need to be cached.

LSWS Cache Policy configuration (Admin Console -> Server/Vhost ->Cache-> Cache Policy).

Cache Policy:
Enable Cache: ==> No
Cache Expire Time (seconds): => Not Set
Cache Request with Query String: => Yes
Cache Request with Cookie: => Yes
Cache Response with Cookie: => Yes
Ignore Request Cache-Control: => Yes
Ignore Response Cache-Control: => Yes
To verify if a resource is served out of LSWS cache is simple, just look for "X-LiteSpeed-Cache: hit" in server response header. If the header is present, the resource IS served from LSWS cache.

HTTP/1.1 200 OK
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Tue, 08 Feb 2011 23:14:38 GMT
Server: LiteSpeed
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
X-LiteSpeed-Cache: hit
Content-Length: 6141
X-Powered-By: PHP/5.2.11
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Content-Type: text/html; charset=utf-8
Expires: Mon, 1 Jan 2001 00:00:00 GMT
Last-Modified: Tue, 08 Feb 2011 23:14:12 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Benchmark Comparison

Following is the ab benchmark of the test sites in our lab against latest Joomla 1.5 (1.5.22) with sample data comes with install.

Litespeed Cache + Joomla 1.5.22 (with NO system cache plugin)
Code:
Benchmarking 192.168.0.56 (be patient).....done


Server Software:        LiteSpeed/4.1RC4
Server Hostname:        192.168.0.56
Server Port:            8088

Document Path:          /joomla-overview.html
Document Length:        12422 bytes

Concurrency Level:      10
Time taken for tests:   0.139489 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      1363478 bytes
HTML transferred:       1316732 bytes
Requests per second:    716.90 [#/sec] (mean)
Time per request:       13.949 [ms] (mean)
Time per request:       1.395 [ms] (mean, across all concurrent requests)
Transfer rate:          9541.97 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:     5   12   4.2     12      22
Waiting:        5   11   3.9     11      21
Total:          5   12   4.2     12      22

Percentage of the requests served within a certain time (ms)
  50%     12
  66%     12
  75%     13
  80%     15
  90%     21
  95%     21
  98%     22
  99%     22
 100%     22 (longest request)
Joomla 1.5.22 with Page Caching (system cache plugin)

Code:
Benchmarking 192.168.0.56 (be patient).....done


Server Software:        LiteSpeed/4.1RC4
Server Hostname:        192.168.0.56
Server Port:            8088

Document Path:          /joomla-overview.html
Document Length:        12537 bytes

Concurrency Level:      10
Time taken for tests:   2.492758 seconds
Complete requests:      100
Failed requests:        0
Write errors:           0
Total transferred:      1306000 bytes
HTML transferred:       1253700 bytes
Requests per second:    40.12 [#/sec] (mean)
Time per request:       249.276 [ms] (mean)
Time per request:       24.928 [ms] (mean, across all concurrent requests)
Transfer rate:          511.48 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:    51  243 159.6    215    1226
Waiting:       43  203 147.5    181    1080
Total:         51  243 159.6    215    1226

Percentage of the requests served within a certain time (ms)
  50%    215
  66%    256
  75%    275
  80%    283
  90%    324
  95%    436
  98%    959
  99%   1226
 100%   1226 (longest request)
Joomla 1.5.22 with NO Page Caching

Code:
Benchmarking 192.168.0.56 (be patient).....done


Server Software:        LiteSpeed/4.1RC4
Server Hostname:        192.168.0.56
Server Port:            8088

Document Path:          /joomla-overview.html
Document Length:        12490 bytes

Concurrency Level:      10
Time taken for tests:   9.218677 seconds
Complete requests:      100
Failed requests:        92
   (Connect: 0, Length: 92, Exceptions: 0)
Write errors:           0
Total transferred:      1296527 bytes
HTML transferred:       1246727 bytes
Requests per second:    10.85 [#/sec] (mean)
Time per request:       921.868 [ms] (mean)
Time per request:       92.187 [ms] (mean, across all concurrent requests)
Transfer rate:          137.33 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.9      0       5
Processing:   256  893 578.1    748    3065
Waiting:      248  828 567.9    694    2878
Total:        256  893 578.1    748    3065

Percentage of the requests served within a certain time (ms)
  50%    748
  66%    868
  75%    933
  80%   1058
  90%   1672
  95%   2396
  98%   2892
  99%   3065
 100%   3065 (longest request)
 
Last edited:

bobykus

Well-Known Member
#9
I wonder why I always get

ip@ip:~/Desktop/hs$ curl -I http://some.dk


HTTP/1.1 200 OK
Date: Fri, 09 Nov 2012 11:36:53 GMT
Server: LiteSpeed
Connection: close
X-Powered-By: PHP/5.3.16
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Set-Cookie: ba5120434de25501685872454c829084=rt2d7if5vp2uioent3o7cee112; path=/
Set-Cookie: ja_opal_tpl=ja_opal; expires=Wed, 30-Oct-2013 11:36:49 GMT; path=/
Content-Type: text/html; charset=utf-8
Expires: Mon, 1 Jan 2001 00:00:00 GMT
Last-Modified: Fri, 09 Nov 2012 11:36:53 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache


Did I miss something in configuration?

Enable Cache No
Cache Expire Time (seconds) 300
Cache Request with Query String Yes
Cache Request with Cookie Yes
Cache Response with Cookie Yes
Ignore Request Cache-Control Yes
Ignore Response Cache-Control Yes
Enable Private Cache Yes
Private Cache Expire Time (seconds) 300

Max Keep-Alive Requests 100
Smart Keep-Alive Yes
Keep-Alive Timeout (secs) 5
 

bobykus

Well-Known Member
#11
Looks like

Storage Path /var/cache/lsws
Max Object Size 1024000


ls -ld /var/cache/lsws
drwxrwxrwt 18 httpd httpd 360 Nov 9 11:31 /var/cache/lsws

df -h
..
tmpfs 512M 13M 500M 3% /var/cache/lsws

and there are fresh files there

/var/cache/lsws/f/f/e:
total 4
drwx------ 2 httpd httpd 60 Nov 12 13:27 .
drwx------ 18 httpd httpd 380 Nov 12 13:30 ..
-rw------- 1 httpd httpd 1155 Nov 12 13:27 ffe60cd8501a2bca
 

bettinz

Well-Known Member
#18
Hello Scot, I've created the plugin for 1.5, 2.5 and 3.x. Now I don't use ls cache anymore, so I can't test the plugin. I hope to use lscache again in future and I hope in a better support for dynamic applications (for example virtuemart for guest, contact forms, or responsive template via mobile joomla stop working)
 

Michael

Well-Known Member
Staff member
#19
This has really become a hot topic recently:

I don't know of anyone making a plugin for Joomla! right now (though I can think of at least one company that might be working on it). I do know of a couple hosting companies that are working on Drupal and/or WordPress plugins, so keep you eyes peeled. We are working on a plugin for Magento right now. We may continue working on plugins for other applications after we have released the Magento plugin, but we will first have to survey the market and decide about other priorities.

m
 
#20
Hello Scot, I've created the plugin for 1.5, 2.5 and 3.x. Now I don't use ls cache anymore, so I can't test the plugin. I hope to use lscache again in future and I hope in a better support for dynamic applications (for example virtuemart for guest, contact forms, or responsive template via mobile joomla stop working)
Hi, could I purchase the Joomla plugin to do some testing? I am finding that just using memcached with 512 MB of RAM I am seeing about 25% faster pageloads. Will be interesting to see what happens if I tried the Litespeed cache add-on for my Litespeed server.
 
Top