Разгоняем django сайт с помощью staticgenerator

Я неспешно переезжаю на VDS от gandi.net. Был дедик с объёмом памяти один гиг, а переезаю на 256 метров. Пока не знаю, удастся ли втиснуться. Конечно же, возникают вопросы, а можно ли убыстрить мои сайты, заставить их жрать меньше памяти. Сегодня ночью я сражался с web-brains, а точнее с byteflow, на котором они работают. Выяснилось, что более одного запроса в секунду apache/mod_wsgi демон не обрабатывает, хоть ты тресни. Я пока не понял, во что именно упирается byteflow, но это не важно в рамках данного сообщения. Решил я закешировать веб-мозги, да так шобы прям в усмерть закешировать. Как раз вчера один знакомый упоминал staticgenerator и я понял — самое время призвать на помощь его мощности статическогенерические.

Идея, лежащая в основе staticgenerator оень простая и дерзкая. Адрес веб-страницы похож на файловый путь. Когда мы запрашиваем страницу /2009/08/07/hello-world, то staticgenerator создаёт в заданном каталоге такую же структуру т.е. каталог 2009, в нём каталог 08, в нём каталог 07, в нём каталог hello-world, а в нём файл index.html, куда и записывается содержимое сгенерированной страницы. Всё это делает специальная middleware. Далее начинается самое интересное, мы настраиваем веб-сервер так, чтобы он смотрел в заданном каталоге закэшированный файл и если там он есть, то файл выдаётся пользователю и джанго-демон даже не дёргается. Вот такие пироги :)

Далее я опишу технические детали того, как я прикрутил staticgenerator конкретно к byteflow.

Для начала неплохо установить staticgenerator через easy_install

Далее идём в settings_local.py проекта и пишем там такое в конце:

# Здесь мы просим staticgenerator складывать кэш файл в каталог нужный
WEB_ROOT = '/web/cache/staticgenerator/web-brains.com'

# Это регулярные выражения. Будут кэшироваться только те страницы, которые
# удовлетворяют выражениям. Я поковырялся в urls файлах byteflow и выбрал те,
# которые относятся к непосредственному отображению данных
STATIC_GENERATOR_URLS = (
    r'^/$',
    r'^/feeds',
    r'^/\d',
    r'^/tag',
    r'^/tags',
    r'^/featured',
    r'^/author',
    r'^/sitemap\.xml',
    r'^/robots\.txt',
)

# Так можно в byteflow добавить новую middleware из setttings.py
ADDITIONAL_MIDDLEWARE= ('staticgenerator.middleware.StaticGeneratorMiddleware',)

Ещё я в settings.py добавил cache_manager в ADDITIONAL_APPS. А что такое cache_manager? А это такое приложение, которое сигналы ловит при создании нового поста или нового комментария и грохает весь кэш. Можно, конечно, хорошо подумать и написать очищение только изменившихся страниц, а можно просто грохнуть быстренько всё :) Я запихал код в cache_manager/__init__.py — таким образом я добился его выполнения при старте сайта т.е. установки нужных обработчиков сигналов.

from subprocess import Popen from staticgenerator import quick_delete

from django.db.models.signals import post_save
from django.conf import settings

from blog.models import Post
from discussion.models import CommentNode

def clear_cache(**kwargs):
    Popen('rm -rf %s/*' % settings.WEB_ROOT, shell=True)

post_save.connect(clear_cache, sender=Post)
post_save.connect(clear_cache, sender=CommentNode)

Код элементартный. Если создали Post или CommentNode — грохаем кэш!

Так, так. Вот мы сайт настроили. Осталось веб-сервер настроить. Веб-сервер у нас, конечно, nginx. У меня такой конфиг для веб-мозгов:

server { server_name .web-brains.com; access_log /var/log/www/web-brains.com-access.log; error_log /var/log/www/web-brains.com-error.log warn;

    include fastcgi_params;

    location /admin-media {
        alias /home/web/lib/django_src/django/contrib/admin/media;
    }
    location /static/ {
        root /web/web_brains;
    }

    # Нас интересует ниженарисованный кусок конфига
    # Делаем корнем для статики тот каталог, куда
    # staticgenerator кэш пишет.
    root /web/cache/staticgenerator/web-brains.com;
    location / {
        # Всё что не GET, отдаём бэкенду. У меня это apache/mod_wsgi
        if ($request_method != GET) {
            proxy_pass http://127.0.0.1:8080;
            break;
        }
        # Вот тут чуток меняем путь поиска т.к. staticgenerator
        #  пишет кэш в index.html файлы
        if (-f $request_filename/index.html) {
            rewrite (.*) $1/index.html break;
        }
        # Если файл таки не нашёлся, идём в бэкенд
        # иначе ничего не делаем и благополучно выкидываем
        # закэшированный файл пользователю
        if (!-f $request_filename) {
            proxy_pass http://127.0.0.1:8080;
            break;
        }
    }
}

Гм, ну вот и всё. Ща сохраню статью и заодно проверю, что кэш грохнулся. Я запускал ab тесты прямо на VPS. Раньше морда веб-мозгов раздавалась со скростью 1page/second, а щас 668pages/second. Клёво :)

Add post to:   Delicious Reddit Slashdot Digg Technorati Google
Make comment

Comments

Спасибо за статью. Я даже придумал, куда это можно применить.

Логин часом не отлетел?:) Я не могу залогиниться для ответа.

А я сейчас не мог удалить комментарий т.к. не было кнопки “Удалить”. А виноват в этом я и косвенно staticgenerator. Суть проста: гость запросил страницу, кэш создался, теперь этот же кэш отдаётся и мне :) И в этом кэше нет ссылки удаления комментария и показано, что я гость. Видимо, это ставит жирный крест на staticgenerator. В любом случае — статью написал и то ладно :)

Джанговский вью-кэш в сочетании с vary_on_cookie пробовали? Делает ровно то, что нужно, разве что фрэймворк дергает при обработке запроса.

По идее, несложно написать бэкэнд к кэшу джанго, который бы позволил кэшировать страницы (и только их) в файловой системе и в дальнейшем раздавать как статику.

В идеале хотелось бы что-то такое привернуть, чтобы не править сорцы byteflow :-) Если не получится, придётся законтрибутить туда кэширование или просто на другой движок съехать.

А почему не linode? Или www.rackspacecloud.com?

У сайта gandi.net красивый дизайн.

А ещё он во Франции — пинг меньше, чем до тех, которые в штатах. А ещё у меня два месяца халявных по акции специальной. И для потестировать тоже бесплатно дают. В общем, приятный сервис.

Еще полтора года назад я переделывал этот статикгенератор в более продвинутую версию. StaticGenerator Pro Там и решение проблемы с юзерами через определение куки сессии в нгинксе есть.

Кстати, джаред(автор генератора) взял у меня версию, чуть изменил, чтобы не совсем уж стыдно потыренной выглядела и никакого упоминания ни обо мне, ни ссылки на блог

Вот гад.

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image