Установка и настройка Django на “боевом” сервере с CentOS 5

Я делаю на Django Энциклопедию языков программирования. За время работы сайта выяснилось, что нужен свой выделенный сервер для большей производительности и стабильности. Пока что взял дешевый сервер с 1.8 ГГц процессором и 512 Мб памяти.

В этой статье я расскажу об установке и настройке на этом сервере Django с mod_python для Apache, с кэшированием memcached и lighttpd для статических файлов.

Итак, у нас есть свежеустановленная CentOS 5 и желание хостить сайт на Django (или несколько сайтов).

Что для этого надо установить?

  1. Собственно Django
  2.  MySQL-python
  3.  mod_python
  4.  memcached
  5.  lighttpd

Все шаги, кроме установки самого Django, — необязательные (например, можно использовать Django с fcgi вместо mod_python и PostgreSQL или другую СУБД вместо MySQL), но шаги 1-3 – то, что вы скорее всего будете использовать, а 4-5 – для повышения производительности.

Статья, в основном, CentOS-ориентированная, но в определенной степени подойдет и для других дистрибутивов Linux.

Замечание по безопасности: так как это свежеустановленная система, я не боюсь сломать что-то уже работающее, так что могу работать под правами root. Но лучше, конечно, работать под правами непривилегированного пользователя, и использовать “sudo” для команд, требующих административные привилегии.

Ну, начнем.

Собственно Django

В большинстве случаев стоит устанавливать самую свежую svn-версию Django, а не “релиз”. На сегодняшний момент, “официальный релиз” слишком устарел, и в нем отсутствует множество полезных возможностей (например, поддержка unicode и auto-escape).

Для установки вводим в командной строке

svn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

Но сначала нужно установить svn

yum install subversion

После получения всех файлов с svn нужно сделать символическую ссылку на Django в директории site-packages для Python :

ln -s `pwd`/django-trunk/django /usr/lib/python2.4/site-packages/django

Убедитесь, что у всех родительских директорий каталога django установлены верные права (доступ на чтение для пользователя httpd, обычно chmod 755).

Также установка Django с svn рассмотрена в официальной документации Django.

После установки Django нужно скопировать на сервер файлы вашего проекта (через svn или просто копированием по ssh или ftp; также стоит завести в системе отдельного пользователя, который будет владельцем этих файлов) и дамп базы данных, а потом подкорректировать связанные с БД настройки в файле settings.py (подразумевается, что MySQL уже установлен и настроен, база данных и пользователь созданы, все данные на месте – эти вещи далеко за рамками этой статьи).

Теперь попробуйте запустить Django development-сервер из директории проекта

python manage.py runserver 127.0.0.1:8000

На CentOS 5 будет сообщение об ошибке “Error loading MySQLdb module”.

Версия MySQL-python в дистрибутиве CentOS слишком старая для запуска свежей svn-версии Django, так что нужно собирать из исходников.

MySQL-python

cd /usr/local/src
wget http://garr.dl.sourceforge.net/sourceforge/mysql-python/MySQL-python-1.2.2.tar.gz
tar xvzf MySQL-python-1.2.2.tar.gz
cd MySQL-python-1.2.2

Для сборки MySQL-python понадобятся пакеты gcc, python-devel и mysql-devel.

yum install gcc
yum install python-devel
yum install mysql-devel

cd /usr/local/src/MySQL-python-1.2.2
python setup.py build
python setup.py install

Готово, MySQL-python установлен как .egg-файл в директории site-packages.

Снова попробуйте запустить python manage.py runserver 127.0.0.1:8000 и проверьте, нет ли каких ошибок. Например, я использую ImageField в своем проекте, так что мне нужно было дополнительно установить Python Imaging Library (yum install python-imaging).

Если ошибок нет, стоит сменить 127.0.0.1 в команде runserver на IP-адрес вашего сервера и проверить работу сайта при помощи браузера, но для этого нужно в брандмауэре CentOS открыть порт 8000 или временно выключить брандмауэр (или можно просто временно выключить Apache и запустить Django development-сервер на 80-том порту).

Если ошибок нет, то самое время выключить Django development-сервер и настроить Apache.

mod_python

Настроить Apache с mod_python на работу с Django просто: достаточно следовать инструкциям из официальной документации Django.

Одно замечание: так как MySQL-python установлен в виде egg-пакета, важно создать временную директорию (установите на нее права 777) для кэширования .egg и указать на нее в httpd.conf

<Location "/">
    ...
    SetEnv PYTHON_EGG_CACHE /var/tmp/egg
</Location>

И не забудьте перезапустить Apache после изменения httpd.conf:

/etc/init.d/httpd restart

Сейчас сайт должен работать через Apache на обычном http-порту. Проверьте браузером.

memcached

Включение кэширования memcached очень важно для увеличения производительности. К сожалению, memcached отсутствует в репозитариях CentOS, так что опять придется собирать из исходников. Этот раздел статьи частично основан на этом HOWTO.

Сначала нужно установить libevent:

cd /usr/local/src
wget http://monkey.org/~provos/libevent-1.4.2-rc.tar.gz 
tar xvzf  libevent-1.4.2-rc.tar.gz
cd libevent-1.4.2-rc
./configure
make
make install

vi /etc/ld.so.conf.d/libevent.conf
## добавьте строку:
/usr/local/lib/

ldconfig -v

Затем собственно memcached:

cd /usr/local/src
wget http://danga.com/memcached/dist/memcached-1.2.5.tar.gz
tar zxvf memcached-1.2.5.tar.gz
cd memcached-1.2.5
./configure
make
make install

cp scripts/memcached.sysv /etc/init.d/memcached

ln /usr/local/bin/memcached /usr/bin/memcached
/etc/init.d/memcached start

chkconfig memcached on

И наконец нужно установить libmemcache и cmemcache (python-расширение для libmemcache):

cd /usr/local/src/
wget http://people.freebsd.org/~seanc/libmemcache/libmemcache-1.4.0.rc2.tar.bz2
bunzip2 libmemcache-1.4.0.rc2.tar.bz2
tar xf libmemcache-1.4.0.rc2.tar
cd libmemcache-1.4.0.rc2
./configure
make 
make install

cd /usr/local/src/
wget http://gijsbert.org/downloads/cmemcache/cmemcache-0.91.tar.bz2
bunzip2 cmemcache-0.91.tar.bz2
tar xf cmemcache-0.91.tar
cd cmemcache-0.91
python setup.py install

Включите memcached-кэширование в settings.py своего проекта

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

(если нужно больше информации, посмотрите в официальной документации Django) и перезапустите Apache.

Чтобы получить еще большую производительность, нужно статические файлы отдавать не при помощи Apache, а менее ресурсоемким сервером – lighttpd.

lighttpd

Опять-таки, устанавливаем из исходников.

cd /usr/local/src
wget http://www.lighttpd.net/download/lighttpd-1.4.19.tar.bz2
bunzip2 lighttpd-1.4.19.tar.bz2
tar xf lighttpd-1.4.19.tar
cd lighttpd-1.4.19
yum install glib2-devel openssl-devel pcre-devel bzip2-devel gzip-devel
./configure
make 
make install

cp doc/rc.lighttpd.redhat /etc/init.d/lighttpd
chkconfig lighttpd on

mkdir /etc/lighttpd
cp doc/lighttpd.conf /etc/lighttpd/

А теперь нужно настроить Apache и lighttpd, чтобы статические файлы отдавались lighttpd (на 80 порту), а остальные запросы обслуживал Apache на 81 порту (спасибо nolancaudill.com за это решение):

  • Настройте Apache на 81 порт: найдите
    Listen 80 и замените на Listen 127.0.0.1:81. Также не забудьте сменить номер порта во всех VirtualHost-директивах. Перезапустите Apache.

  • Отредактируйте /etc/lighttpd/lighttpd.conf. Снимите комментарии с модулей ‘mod_alias’ и ‘mod_proxy’ и добавьте строки (подкорректируйте под свои нужды):

    $HTTP["host"] == "yourdomain.com" {
    
        # here we are mapping /media/ for admin media
        # and /static/ for the standard media_url
        alias.url = (
           "/media/" => "/usr/lib/python2.4/site-packages/django/contrib/admin/media/",
           "/static/" => "/var/www/html/media.yourdomain.com/",
        )
    
    
        $HTTP["url"] !~ "^/(static|media)/" {
            proxy.server = ( "" => (("host" => "127.0.0.1", "port" => 81 )) )
    
        }
    
    }
    

Также смените server.document-root на “/var/www/html/” и создайте символическую ссылку “/var/www/html/media.yourdomain.com/”, указывающую на media-директорию вашего проекта.

  • Cоздайте директорию для лог-файлов lighttpd:

    mkdir /var/log/lighttpd/
    
  • Еще одна маленькая правка в /etc/init.d/lighttpd: смените пусть с /usr/sbin/lighttpd на /usr/local/sbin/lighttpd. Запустите lighttpd:

    /etc/init.d/lighttpd start
    

И в конце еще несколько советов по производительности:

Add post to:   Delicious Bobrdobr.ru Memori.ru Mister-Wong.ru Yandex.ru Myscoop.ru
Make comment

Comments

Все хорошо, но если была проблема с производительностью, то почему apache? В документации утверждается, что можно получить прирост производительности с lighttpd и fastcgi. Apache действительно тяжелый, если не нужна какая-то специфичная функциональность apache — почему бы и нет?

Сергей 21.04.2008 15:15

Я ставил то, что рекомендуется в официальной документации. Apache + mod_python. lighttpd рекомендуется только для отдачи статики, про fastcgi написано, что, возможно, будет быстрее, но пока все же рекомендуется mod_python.

В будущем, может попробую убрать Apache.

Я бы порекомендовал mod_wsgi, он выходит быстрее и менее памятежорный. :-)

Игры с nginx/lighttpd показали, что fastcgi памяти ест не меньше, но зато менее стабилен (за ним надо глаз да глаз, чтоб был живой, плюс течёт, а апач автоматически запускает новые на N запросов). Потому остался nginx как фронтенд (который сервит статику) и апач на бекенде.

могу дать пример конфига для nginx. Сильно ничего не придумывал, работает as is. Вроде достаточно шустренько все…

некто 21.04.2008 14:25

И зачем здесь нужно было под рутом работать?

Сергей 21.04.2008 15:16

Ну, apache перезапускать, make install делать, rmp-пакеты устанавливать…

Илья Колесников 21.04.2008 15:18

Классная статья, огромное спасибо! Подскажите пожалуйста, каким хостингом пользовались до перехода на новый сервак, и каким хостингом пользуетесь теперь? (что-бы не было рекламы :) 2tl@mail.ru )

Сергей 21.04.2008 15:32

Да могу и здесь написать.

Виртуальный хостинг с Django — чуть ли не единственный, что я смог найти на просторах СНГ — http://tophost.com.ua/. В общем-то неплохой, но Load Average там частенько 5-6 а то и 10-15 бывает.

Сейчас арендую выделенный сервер в США: http://meganetserve.com/

Еще попробовал VDS — не советую, разве что только для экспериментов. Со скоростью проблемы, часто медленнее, чем на виртуальном хостинге.

Мне кажется, что вместо компиляции memcached из исходников лучше добавить в yum репозиторий rpmforge, тогда не будет проблем с обновлениями.

Сергей 21.04.2008 16:37

Может, с определенной точки зрения и лучше. Но мне не хотелось сторонние репозитарии добавлять…

К тому же, там сейчас довольно старая версия memchached. А например, cmemcache нет вообще. Т.е. все равно пришлось бы что-то компилировать.

Уважаемый Сергей,

Статья хорошая; только один вопрос: зачем собирать ПО с исходников методом “./configure; make; make install”, если можно взять .src.rpm-пакет от Fedora (версий от 6 и до 9) и с помощью rpmbuild пересобрать его под el5?


С Уважением,

Alex Slesarev 21.04.2008 15:41

А зачем ln -s pwd/django-trunk/django /usr/lib/python2.4/site-packages/django?

Думаю лучше и более корректно просто проинсталлировать выкачанный транк: sudo python setup.py install

К тому же инсталлятор сделает все нужные чмоды. А если стоит SELinux, то это единственный верный вариант, т.к. иначе файлы будут не с тем контекстом.

И еще, хотел бы заметить (т.к. с этим сами столкнулись) — надо настроить MySQL сразу на работу с Unicode, иначе потом не огрестить проблем с вылетом сайта на русских текстах.

И еще :) По-хорошему, процедура запуска сайта должна состоять из следующих шагов (для удобства предварительно сделав chmod +x manage.py): 1) ./manage.py syncdb 2) ./manage.py test 3) ./manage.py validate Ну и потом уже runserver (в принципе, он тоже запускает validate). А тесты нужны, настоящий питонист без тестов никуда :))

Сергей 21.04.2008 23:53

ln -s pwd/django-trunk/django /usr/lib/python2.4/site-packages/django — это из официальной документации. sudo python setup.py install действительно удобнее. Только надо не забывать устанавливать каждый раз после обновления с svn.

Виктор 21.04.2008 23:46
  1. Вот не надо апач на 81-й порт вешать! Поверьте, просто не надо! Только на 80-й. Иначе потом не оберётесь проблем в самых неожиданных местах. Я уже через это проходил.

  2. Вместо lighttp можно использовать nginx

  3. То чего нет в дистрибутиве CentOS можно спокойно взять в виде нормальных src.rpm в репозитарии Extras для Fedora Core 6 или в Fedora Everything в более поздних версиях Fedora. Собирается практически всё сразу же без напильников.

мне кажется что на люой порт можно вешать… у меня весит три сайта по fcgi на localhost на портах 8081 8082 8083…=)дискомфорта не испытываю

Имхо, если говорить о высокопроизводительном веб-сервере, то 1. От апачи нужно отказаться. 2. Нужно использовать нечто более быстрое нежели MySQL, вполне PostgreSQL подойдет, тем более что даже с бубном плясать не надо будет. 3. С NGINX сервер стабилен, работаю на этой связке уже полгода, сбоев не было ни разу. 4. Перед всей кухней надо использовать реверсивный проксик, для кэширования особо частых запросов. 5. Ну и уж если говорить о стабильности, то ну никак нельзя юзать транк, только стабильные версии…

  1. От апачи нужно отказаться.

Заявление крайне спорное. ;-)

Виктор 22.04.2008 6:03

ln -s `pwd`/django-trunk/django /usr/lib/python2.4/site-packages/django

может я чего-то не понимаю, но уверен что правильнее воспользоваться setuptools, т.е. написать python setup.py install

ммм.. чего-то я не осилил смысла статьи…

feed не работает http://mydjango.ru/feeds/blog/

Сергей 23.04.2008 6:27

А в какой читалке? Я проверил во встроенной в Firefox и в Akregator. И там, и там - работает.

У меня прекрасно работает.

@Александр Соловьёв

Баловался — с моей точки зрения — не спорное. А как новинка — можете глянуть на tornado+nginx :)

@all

ln -s pwd/django-trunk/django /usr/lib/python2.4/site-packages/django

А почему нет? Вообще создаю симлинк в рабочей директории — разные проекты могут требовать разных версий.

P.S.капча улыбнула =) (стояло foobar, но при отсылке говорило Wrong answer)

Required. 30 chars of fewer.

Required.

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