Долго изучал различные модули для кэширования, после чего быстренько сделал собственный патчик.
Может кому и пригодится.
Основные идеи:
1. Простота.
2. По возможности не дёргать БД. за счёт этого страница из кэша отдаётся в несколько сотен раз быстрее, чем обычная.
3. Кэшируем только анонимов. Если им разрешены постинги - будут проблемы.
Реализация:
1. Создать папку для кэша: mkdir /tmp/cache, chmod 777 /tmp/cache
2. В index.php, в самом начале, до bootstrap (<?phprequire_once './includes/bootstrap.inc';drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);?>
) добавить:
<?php
Global $time1;
$time1 = microtime(1);
function logcache($s) {
Global $time1;
$log = fopen("/var/log/drupal-cache.log", 'a');
fwrite ($log, $s.', ' . ((int)(1000*(microtime(1) - $time1))) . " ms used\n");
fclose ($log);
}
$req = $_SERVER['REQUEST_URI'];
if (empty($_POST) && !isset($_COOKIE['drupal_uid']) && !strstr($req, '/admin') && !strstr($req, 'AJAX')) {
$f = '/tmp/cache/'.strtr($req, '/', '_');
if (file_exists($f) && time() - filemtime($f) < 13*60) {
readfile($f);
logcache ("+ $req served from cache");
exit;
} else {
ob_start();
}
} else {
$f = '';
}
?>
3. В самом конце, после drupal_page_footer():
<?php
Global $user;
if ($user->uid) setcookie('drupal_uid', $user->uid, time() + (60 * 60 * 24 * 30), '/');
Global $nofilecache;
if (!$nofilecache && $f) {
if (file_exists($f)) $cachetime = (int)((time() - filemtime($f))/60);
$fh = fopen($f, 'w');
fwrite($fh, ob_get_contents());
fclose($fh);
ob_end_flush();
if ($cachetime) logcache("- $req replaced - has $cachetime min old");
else logcache ("- $req created cache");
} else {
logcache ("* $req no cache, uid = ".$_COOKIE['drupal_uid']);
}
?>
4. В includes/common.inc, в начале функции drupal_goto, чтобы не кэшировать редиректы
<?php
Global $nofilecache;
$nofilecache = 1;
?>
5. В крон:
Сервер разгружается весьма заметно.
Сейчас работает на http://lib.rus.ec, проблем не замечено.
Комментарии
Интересно, спасибо.
Позволил себе разукрасить ваш код в разные цвета...
Спасибо за решение.
Можно ли его применять и в Д5, и в Д6?
Спасибо, так смотрится лучше.
Я применяю Д6, но должно работать в любом. Всё же очень примитивно сделано.
Кэш в файлах.
Авторы, предложившие решения, также указаны в сохранённой статье.
жесть. а посмотреть документацию, cache.inc на тему cache_page и bootstrap.inc же на тему подмены и на уровне cache_page - складывать в файлы? заодно там чистку.
Посмотрите мой блог - увидите решения
11 * * * * find /tmp/cache/ -mmin 15 -delete - это жестоко несколько, не находите?
это жестоко, так и задумывалось.
Зато эффективно.
Не надо лишний раз логиниться к базе, что у меня бывало узким местом.
Суть в том, что страница из кеша отдаётся до бутстрапа. Без попытки связаться с базой. Что заметно ускоряет. И этот хак годится без изменения для любой версии друпала.
Find отрабатывает намного быстрее, чем cron.php, и ресурсов не жрёт. Можно вместо него tmpwatch использовать, если он есть в системе.
Я пересмотрел все существующие решения, если бы нашёл меня устроившее - не стал бы заморачиваться. Уже само количество вариантов кэширования говорит о том, что хорошего нет. У каждого свои плюсы и минусы. Как и у моего естественно.
А какие именно могут проблемы возникнуть? Свои собственные посты не увидят или что-то похуже?
А можно ли сделать кэш для зарегистрированных пользователей тоже?
Заранее спасибо за ответ.
Именно что не увидят свои посты. И не только свои. Все свежие (моложе времени кэша)
Если разрешать кэш для залониненных пользователей, то надо как-то такие ситуации отслеживать. Добавлять сброс при появлении новых нод, комментов и при изменении нод. Учитывать алиасы. Сделать можно, но не слышал, чтоб кто-нибудь брался. Работы много, толку мало.
Еще у пользователей бывают разные роли. Разным ролям показывают разный контент.
Ещё бывают блоки, типа лички, которые для всех уникальны. И, скажем, на Либрусеке, блок личных сообщений показывается на большинстве страниц.
А если все зарегистрированные пользователи видят одно и тоже, то в чём смысл регистрации?
find /tmp/cache/ -mmin 15 -delete
))) что это за кеш который сам сбрасывается? в случае большого количества страниц он будет просто мешать а не помогать так как вероятность и частота запроса определенной страницы уменьшается пропорционально их количеству, и когда работа сайта зависит от количества страниц - то это не правильный сайт
Топик стартеру: копать в сторону drupal_bootstrap в фазе DRUPAL_BOOTSTRAP_EARLY_PAGE_CACHE там есть page_cache_fastpath()
Посмотрите также cacherouter для 6й версии - там есть кеш на файлах!
Ну и перед записью в файл его неплохо было бы блокировать...