This page has been moved, the new location is lscache.

LiteSpeed Cache (LSCache) Introduction

LiteSpeed has created a built-in cache functionality (an advanced feature for Enterprise 2+CPU license. Available since version 4.0 (March, 2009), its performance keeps improving throughout the later 4.0.x and 4.1RC releases. As of 4.1.1 (May, 2011), private cache support is added.

LiteSpeed's cache features are very similar to those in Apache mod_cache, but implemented in a more efficient way. LiteSpeed cache works like Varnish. It is an output cache for dynamic contents, so the usage is not limited to PHP pages. Unlike Varnish, LiteSpeed cache is built into LiteSpeed's web server, thus eliminating one layer of reverse proxy. This translates into higher efficieny for static contents. The uniqueness of LiteSpeed cache is that it uses rewrite rules (either in configuration files or .htaccess) to control its behavior for maximum flexibility.

A general way to enable LiteSpeed Cache through rewrite rules is to designate a signature token (such as cookie) in any page, in most cases it will tell LSWS that cache can be enabled and that the TTL(Time To Live) of the cache freshness will remain acceptable. Generating cookies usually requires application code modification. Please refer to http://www.litespeedtech.com/support/forum/showthread.php?t=4679 for examples. It is worth noting that the cache function SHOULD ONLY be used for pages that are supposed to be cached or cache friendly. Abuse use of this feature would result in performance degradation and/or other unexpectancies.

Since 4.1.1 (May, 2011), private cache support has been added. Private cache is for caching resources for individual specifically instead of public shared. The purposes are:

  • maintain a persistent cache for applications that do not have a shared cache.
  • maintain a private persistent cache for specific groups of documents that are not to be shared among other applications.

Public Cache vs. Private Cache

A public, or “shared” cache is used by more than one client. As such it gives a greater performance gain and a much greater scalability gain, as a user may receive cached copies of representations without ever having obtained a copy directly from the origin server. Reverse Proxies (gateway caches) and the vast majority of proxies are public caches.

A private cache is only used by one client. Generally this applies only to a cache maintained by that client itself, though if you had a proxy that was only being used by one client (say you had a small LAN for your own use only and put a web proxy near the gateway) it would be possible to configure it to act as a private cache. Private caches do not offer quite as much scalability as public caches, but they do have certain important advantages over public caches:

  1. They offer immense benefits to the user of that one client.
  2. Almost every client on the visible web (that is, browsers, RSS readers, and other interactive user agents) and a very large number of those on the machine-only parts of the web (that is, spiders and clients of webservices) use a private cache of some sort. As such you can rely upon the presence of at least one cache being involved in almost everything you do on the web.
  3. With some representations it may not be appropriate for public caches to cache them or to return those representations without re-validating them but perfectly acceptable for private caches to do so (e.g. anything which can only be seen by authorized users or which changes its representation depending upon who is looking at it). It can even be appropriate for encrypted documents to be so cached (though this requires one to be very sure as to the security of the cache itself, and so is generally not done)

When to use public cache, private cache, or not to cache

  • Public cache
    1. Can be shared by many users such as site logo, navigation images, js, css, etc.
    2. Change infrequently
    3. Popular demand (requested frequently)
  • Private cache
    1. Can only be used by one user/client such as personal information on web site (for authorized user)
    2. Resource such as documents only available for one particular user or authorized user.
    3. Resource served via HTTPS protocol
    4. Response with cookie
  • No cache
    1. POST request
    2. Dynamic content (such as time sensitive info)
    3. Frequent changed objects

How to enable LiteSpeed Cache

Although there is a advanced setting "Enable Cache" in LSWS Wed Admin Console on both server and virtual host level, “No” is always recommended since globally enabled public cache may cause problem when URLs change or other changes on the domain. We recommend to enable cache through rewrite rules. Here are the steps to enable LSWS built-in cache:

1. Enable cache function at Server level in LSWS

  • LSWS Web Admin Console→Server→Cache
  • Cache Storage Settings→Storage Path: set to a fast local disk, e.g. /tmp/diskcache (set it to a ramdisk such as /dev/shm/lsdiskcache if enough extra memory can be spared to speed up further)
  • Manually create the directory from shell, and give write permission for litespeed/lshttpd processes (assume running as “nobody” here):
# mkdir /tmp/diskcache
	
# chown nobody:nobody /tmp/diskcache
	      
# chmod 700 /tmp/diskcache

2. Set Default cache policy at LSWS Server level

LSWS Web Admin Console→Virtual Hosts→mytest→Cache → Cache Policy

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

Note:

  1. Even though Cache is disabled globally at Server Level, it will be enabled through rewrite rules. That's the way supposed to be.
  2. Cache Request with Cookie can be set to Yes as long as cookie does NOT affect the generated page. Use it carefully.
  3. Set “Enable Private Cache” to Yes to turn on private cache. Private Cache is pertinent to each individual user/browser. This is to speed up performance even for logged-in user or cache for individual instead of public.

3. For imported Apache vhost: Cache can be turned on/off with “CacheEnable” , “CacheDisable” directives in Apache config file: .htaccess (preferred) or httpd.conf, etc. Nothing needs to be done for the cache policy. It will assume the same default settings at LSWS Server level.

  • To enable private cache, you can add to .htaccess under document root of the web site,
<IfModule LiteSpeed> 
CacheEnable private /
</IfModule> 
  • To disable private cache,
<IfModule LiteSpeed> 
CacheDisable private /
</IfModule> 
  • To enable public cache,
<IfModule LiteSpeed> 
CacheEnable public /
</IfModule> 
  • To disable public cache,
<IfModule LiteSpeed> 
CacheDisable public /
</IfModule> 

To enable/disable cache for certain URL, just replace “/” with desired URL.

Rewrite rules can be placed in httpd.conf or in-directory .htaccess file as shown in step 5 below.

Note:

  • Apache mod_cache directives CacheIgnoreCacheControl, CacheMaxExpire also can be used in the Apache config file (httpd.conf or .htaccess) to fine tune cache policy.
  • WHM/cPanel user: since cPanel does not have an option to enable mod_cache, mod_cache directives such as CacheEnable, CacheDisable, etc, needs to be manually added to Apache config file: .htaccess or httpd.conf, etc.

4. For native LSWS vhost:

Setup Cache Policy (LSWS Web Admin Console→Virtual Hosts→mytest→Cache → Cache Policy)

Enable Cache:No
Cache Request with Query String:yes		
Cache Request with Cookie:Not Set	
Cache Response with Cookie:Not Set		
Ignore Request Cache-Control:No
t Set		
Ignore Response Cache-Control:Not Set
Enable Private Cache: Not Set
Private Cache Expire Time (seconds): Not Set

Note: those with not set, settings at LSWS Server Level will be assumed.

5. Create/Add rewrite rules for caching

RewriteEngine On
## cache should be available for HEAD or GET requests
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
## select which pages to cache
RewriteCond %{HTTP_COOKIE} page_contain_cachetoken=yes
# with other condition

RewriteCond %{QUERY_STRING} !s=[a-fA-F0-9]{32}

# excluding certain URLs
RewriteCond %{REQUEST_URI} !/(login|register|usercp|private|profile|cron|image)\.php$

# cache for 2 mins for php pages only
RewriteRule /(.*\.php)?$ – [L,E=Cache-Control:max-age=120]
# for those not met above condition, enable private cache.
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
## select which pages to serve from private cache
RewriteCond %{HTTP_COOKIE} !page_contain_cachetoken=yes
# with other condition

RewriteCond %{QUERY_STRING} !s=[a-fA-F0-9]{32}

# excluding certain URLs
RewriteCond %{REQUEST_URI} !/(login|register|usercp|private|profile|cron|image)\.php$

# private cache for however long set in cache policy for php pages only
RewriteRule /(.*\.php)?$ – [L,E=Cache-Control:private]

These rules can be placed in one of the 3 locations below:

  • .htaccess (last line needs to changed as follows:)
RewriteRule (.*\.php)?$ – [L,E=Cache-Control:max-age=120]
RewriteRule (.*\.php)?$ – [L,E=Cache-Control:private]
  • VirutalHost secion in Apache config file
  • LiteSpeed native configuration: Web Admin Console → Configurations → Virtual Hosts → Rewrite

6. Restart LSWS to make changes effective.

Admin Console → Actions → Graceful Restart or issue '/path/to/lsws/bin/lswsctrl restart' from command line.

7. Verify if pages are served from LSWS cache

Since 4.0.19 release, LiteSpeed outputs a response header “X-LiteSpeed-Cache: hit” if a request is served from cache.

Since 4.1.1 release, LiteSpeed outputs a response header “X-LiteSpeed-Cache: hit,private” if a request is served from private cache.

Note: LSCache hit rate is calculated based on all files served. Many of the files served by LSWS, like CSS or HTML, are intentionally not cached by LSCache. Because these files are included in the LSCache hit rate calculation, the hit rate may sometimes look much lower than one might expect.

8. Cache clean up (Optional) Setup a cronjob to purge outdated cache file on disk and add the following entry in /etc/crontab

  • /10 * * * * root find /tmp/diskcache -type f -mmin +8 -delete 2>/dev/null

Note: The cronjob deletes cached files that are more than 8 minutes old every 10 minutes. Since the cache TTL is set at 120 seconds (2 minutes), it's safe to delete those old files that are way passed TTL.

Examples

.htaccess Rewrite Rule Examples:

Cache everything for 2 mins (Simple!)

RewriteEngine On
RewriteRule cacheable/(.*\.php)?$ - [L,E=cache-control:max-age=120]

Note: Only cache *.php files in “cacheable” directory. As pointed out previously, it is a good practice to cache only the files that are supposed to be cached.

Only cache the page with certain signature

RewriteEngine On
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 
# this part is for public 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]

Note: This example demonstrate how LSWS cache rewrite rules fit in application's rewrite rules. The first part is from application (such as joomla). Essentially everything goes through index.php (joomla framework) to process.

Second part of ruleset indicates that LSWS only cache

  • HEAD and GET type request AND
  • The request doesn't contain loginuser in cookie AND
  • %{ORG_REQ_URI} i.e. original request (Note: %{ORG_REQ_URI} is LiteSpeed specific variable. In this case, it keeps the value of %{REQUEST_URI} prior to rewrite to index.php in the first part) does not start with /index.php and not start with /administrator/ AND
  • %{ORG_REQ_URI} ends with .php or .html or .htm or etc.
  • The TTL of cache is 300 seconds (5 minutes).

This example is for private cache

RewriteEngine On
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 
# this part is for private cache, note that HTTP_COOKIE is for loginuser
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
RewriteCond %{HTTP_COOKIE} loginuser
RewriteCond %{ORG_REQ_URI} !^/index.php$
# there is no need to exclude admin area. it can be private cached.
# RewriteCond %{ORG_REQ_URI} !^/administrator/
RewriteCond %{ORG_REQ_URI} (\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$  [NC]
RewriteRule .* - [E=Cache-Control:private,L]

The ruleset indicates that LSWS only private cache

  • HEAD and GET type request AND
  • The request DOES contain loginuser in cookie AND
  • %{ORG_REQ_URI} i.e. original request (Note: %{ORG_REQ_URI} is LiteSpeed specific variable. In this case, it keeps the value of %{REQUEST_URI} prior to rewrite to index.php in the first part) does not start with /index.php AND
  • %{ORG_REQ_URI} ends with .php or .html or .htm or etc.
  • The TTL of cache is however long set in cache policy for private cache.

Disable cache for certain domain when private cache enabled by default

When private cache is enabled (in cache policy), it is enabled for all the domains/vhost. However, certain domain/vhost may not work well when private cache is on by default. In this case, we need to disable private cache for those domains/vhosts.

To do so,

  1. Purge private cache copy if still valid(fresh).
  2. put the following entry in .htaccess under document root of the domain/virtual host in question.
RewriteEngine On
RewriteRule .* - [E=Cache-Control:no-cache] 

or put the following in vhost section of httpd.conf

CacheDisable private