We in http://www.lahaine.org have the same problems as http://forums.b2evolution.net/viewtopic.php?t=15895 (lots of visits and complains of our server), and because we are preparing the upgrade to 2.4.2, we made this very simple hack, based mostly on Hyper Cache: http://www.satollo.com/english/wordpress/hyper-cache, whith ideas from Simple Cache Hack v0.3: http://forums.b2evolution.net/viewtopic.php?p=25724#25724 and 1 Blog Cacher: http://1blogcacher.com/features-and-download.
The hack starts up just after a user requests a page, and just before b2evo starts to send queries to the database. If the page requested is already in cache, it sends the content back and stop; otherwise it creates the page. There is no expiration time for cached files, we just run delete_cache() every time something is updated/created/deleted (as in Cache Hack v0.3).
It works quite OK in our local Apache with b2evo 2.4.2 (31 000 posts), we haven't upload yet to the remote server, but html is html. As URLĀ“s we use Explicit param on index.php and Use param: post ID, so the hack is made based on those parameters. It is a very basic job, but it works, and can give ideas.
The first thing is to fill the config parameters, just put in conf/_advanced.php (or other config file):
$my_cache_enabled = true;
$my_cachedir = $basepath.'mycache';
You have to create the directory whith permissions to read and write.
Then in index.php, just after
require_once $inc_path.'_main.inc.php';
put
my_cache_exists();
Then, if you haven't created a conf/hacks.php file before, create a dummy (empty) conf/hacks.php, and add the following lines:
<?php
/////////////////////////////////////////////////////////////////////////
// Very simple Page Caching Hack
//
// Based mostly on Hyper Cache: http://www.satollo.com/english/wordpress/hyper-cache
// whith ideas from Simple Cache Hack v0.3: http://forums.b2evolution.net/viewtopic.php?p=25724#25724
// and 1 Blog Cacher: http://1blogcacher.com/features-and-download
//
// By: www.lahaine.org
//
/////////////////////////////////////////////////////////////////////////
// Caching routine, if everything is ok
function my_cache_exists()
{
global $preview, $my_file, $my_cache_enabled, $my_cachedir;
// Config values and check if dir has been created
if( !$my_cache_enabled || !$my_cachedir || ( !is_dir($my_cachedir) ) )
{
return false;
}
// The server itself requested that page. (create, update... don't use caching)
if( strcmp( $_SERVER[ 'SERVER_ADDR' ], $_SERVER[ 'REMOTE_ADDR' ] ) == 0 )
{
return false;
}
elseif( $preview )
{ // We don't cache previews
return false;
}
// Reject User Agents in order to avoid over-caching from search engines
if( !defined('OBC_REJECTED_USER_AGENTS') )
define( "OBC_REJECTED_USER_AGENTS", "bot, ia_archive, slurp, crawl, spider" );
$user_agent = strtolower( $_SERVER["HTTP_USER_AGENT"] );
$obc_rejected_user_agents = explode( ",", OBC_REJECTED_USER_AGENTS );
$obc_rejected_user_agents = array_filter( $obc_rejected_user_agents );
if( count($obc_rejected_user_agents ))
{
foreach( $obc_rejected_user_agents as $x=>$rejected_user_agent )
{
$rejected_user_agent = trim( strtolower( $rejected_user_agent ));
if( strpos( $user_agent,$rejected_user_agent ) !== false )
{
return false;
}
}
}
// Do not cache post request (comments, plugins and so on)
if( $_SERVER["REQUEST_METHOD"] == 'POST' )
{
return false;
}
/////////////////////////////////////////////////////////////////////////
// We are going to use the cached file, if exists
get_filename(); // Get name of the file
if( is_file($my_file) )
{ // File exists, then display it
$hyper_data = unserialize( file_get_contents($my_file) );
if( $hyper_data != null && $hyper_data['html'] != '' )
{
// $Hit->log(); // We don't use it, but it should be here
echo $hyper_data['html'];
echo '<!-- hyper cache -->';
flush();
die();
}
else
{ //ERROR, problems in the cache file
return false;
}
}
// The cache file doesn't exists. Now we start the caching
ob_start('hyper_cache_callback');
}
/////////////////////////////////////////////////////////////////////////
function hyper_cache_callback( $buffer )
{
global $my_file;
get_filename(); // Get name of the file
$data['uri'] = $_SERVER['REQUEST_URI'];
$data['referer'] = $_SERVER['HTTP_REFERER'];
$data['time'] = time();
$data['mime'] = 'text/html;charset=UTF-8';
$data['html'] = $buffer;
// Write the file and return
$file = fopen($my_file, 'w');
fwrite($file, serialize($data));
fclose($file);
return $buffer;
}
/////////////////////////////////////////////////////////////////////////
// Get name of the file
// We use index.html for the homepage file and 999.html for the post files
function get_filename()
{
global $my_cachedir, $my_file, $baseurl, $baseurlroot;
$sPathRU = $_SERVER['REQUEST_URI'];
$my_urlbase = substr( $baseurl, strlen( $baseurlroot ) );
$my_urlind = $my_urlbase.'index.php';
$p_exists_1 = explode( "?p=", $sPathRU ); // The actual URI uses ?p=
$p_exists_2 = explode( "&p=", $sPathRU ); // The actual URI uses &p=
if( ( $sPathRU == $my_urlbase ) || ( $sPathRU == $my_urlind ) )
{ // the request comes from the homepage
$my_file = $my_cachedir.'/index.html';
}
elseif( !empty($p_exists_1[1]) )
{ // the request comes from a posts page
$my_file = $my_cachedir.'/'.$p_exists_1[1].'.html';
}
elseif( !empty($p_exists_2[1]) )
{ // the request comes from a posts page
$my_file = $my_cachedir.'/'.$p_exists_2[1].'.html';
}
else
{ // Any other request. We just want to use the caching system in those two cases
// (homepage and posts with p=), you can add other cases
return false;
}
return $my_file;
}
/////////////////////////////////////////////////////////////////////////
// Delete all files in cache dir or just what you select, you decide where and when to call it,
// depending on the frecuency of your post creation/updating, the volume of comments, etc.
function delete_cache( $del_what )
{
global $my_cachedir;
if ($handle = opendir($my_cachedir))
{
if( $del_what == 'all' )
{
while ($file = readdir($handle))
{
if ($file != '.' && $file != '..')
unlink($my_cachedir . '/' . $file);
}
}
else
{ // delete only $del_what
unlink($my_cachedir . '/' . $del_what . '.html');
}
}
}
?>
Hi, this sounds like a nice solution to server overload.
I'm testing now in my development server, bu I have a question for you: how would you go about knowing whether this is really taking some load off the server?
I see your site is quite fast (firebug reports in the order on 1 - 2 seconds to load every page). Did you already implemented this hack in your production server?