Drupal и nginx - увеличиваем производительность

среда, 30 января 2008 г.

Раз уж взялся за изучение Drupal, то решил в самом начале рассмотреть вопросы, связанные с оптимизацией этой мощной CMS.

Пролистав форум на drupal.ru наткнулся на многочисленные отзывы, суть которых состояла в том, что Drupal сильно тормозит, причем даже сразу после установки. Что уж говорить о дальнейшем расширении, использовании многочисленных модулей и различных наворотов.

Особенно остро проблема стоит с хостингом под Друпал, с которой и я столкнулся. Оценить скорость работы Друпала просто не было возможности - всевозможные модули требовали достаточно много памяти для установки, а хостер в этом отношении принял жесткие позиции и ни за какие доплаты не согласился выделять столь нужные дополнительные мегабайты для адекватной работы Друпала :(

Выбор хостинга под Друпал - весьма проблемное занятие. Из того, что можно посоветовать - Мастерхост с своими заоблачными ценами и nic.ru. При выборе хостинга следует ориентироваться на тарифные планы, которые соответствуют техническим требованиям CMS «Битрикс: Управление сайтом» - данная система очень широко распространена и многие хостинг-компании дополнительно указывают возможность работы этой cms на различных тарифных планах ( например, так делает вышеупомянутый Мастерхост ).

Но имея у себя дома стационарную машинку с gentoo на борту, открывается широкое поле для экспериментов с собственным хостингом. В то же время возникают другие проблемы, связанные с оптимизацией работы самой системы в качестве веб-сервера.

Ознакомившись с множеством записей в блогах и форумных топиках, пришел к выводу, что для моих целей лучше всего подойдет не стандартная связка apache + php + mysql, а разработанный Игорем Сысоевым веб-сервер Nginx + fastcgi

Ссылки по теме:
Официальная страничка Nginx
Информационный портал о Nginx
Примеры конфигурации Nginx
Немного информации о Fastcgi

Поднять Nginx не составило особого труда - достаточно было воспользоваться гентушным emerge ( emerge nginx ), в результате чего веб сервер готов к использованию.

Для запуска PHP как FastCGI сервера откопал два способа:
  1. Использование встроенной утилиты в веб-сервер lighttpd ( spawn-fcgi )
  2. Установка поверх PHP патча php-fpm (страничка проекта)
Я воспользовался первым вариантом, так как немного ранее тестировал веб-сервер lighttpd. Ознакомиться с данным методом можно на официальном сайте проекта.

Теперь уже установлена связка Nginx + FastCGI и следует все хорошо настроить :) Nginx - отлично настраиваемый веб-сервер, параметры настройки хорошо документированы на официальном сайте (см. ссылку выше по тексту).

Но одного лишь списка документированных возможностей не достаточно. Чтобы указать серверу где располагается дирректория сайта, настроить ЧПУ в Drupal (точнее, rewrite на самом веб-сервере) и подгрузку статичной инфорации пришлось облазить весь интернет. Поэтому выкладываю ссылки на наиболее грамотно написанные статьи:
После прочтения этих и многих других мануалов и статей решил вынести конфигурацию хостов в отдельные файлы. Для этого в основном конфигурационном файле Nginx следует прописать:
include vhost/*.conf;
Где vhost - дирректория с конфигурационными файлами каждого из хостов (расположение дирректории указано относительно расположения конфигурационного файла).

На данный момент рабочая, но не сильно настроенная конфигурация Nginx у меня выглядит следующим образом:
user someone;
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 128;
sendfile on;
keepalive_timeout 20;
tcp_nodelay on;
#gzip on;
#log_format main '$remote_addr - $remote_user [$time_local] $request '
# '"$status" $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
#tcp_nopush on;
#keepalive_timeout 0;
include vhost/*.conf;
}

Расположение mime.types у вас может быть другим.

Файлы vhost/*.conf содержат в себе конфигурацию хостов. Для Drupal у меня вышел примерно следующий конфиг, поддерживающий ЧПУ и адекватно работающий с загрузкой статической информации (картинки, стили и тд):
##### sitename.tld #####

server {
listen 80;
server_name
sitename.tld www.sitename.tld;
#charset koi8-r;
#access_log logs/host.access.log main;
sendfile on;
keepalive_timeout 65;

location / {
root
* путь до дирректории с файлами Drupal, наприме /var/www/site1/htdocs *;
index index.php index.html index.htm;
if (!-e $request_filename ) {
rewrite ^/(.*)$ /index.php?q=$1;
}
}

error_page 404 /index.php;
# serve static files directly

location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico)$ {
root
* путь до дирректории с файлами Drupal, наприме /var/www/site1/htdocs *;
access_log off;
expires 30d;
}

# redirect server error pages to the static page /50x.html
#
#error_page 500 502 503 504 /50x.html;

#location = /50x.html {
# root html;
#}

location ~ \.php$ {
fastcgi_pass 127.0.0.1:8888;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME
* путь до дирректории с файлами Drupal, наприме /var/www/site1/htdocs *$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;

# вставка #
fastcgi_param REMOTE_ADDR $remote_addr;
#fastcgi_param PATH_TRANSLATED $fastcgi_path_translated;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}

}
##### sitename.tld #####

С этой настройкой на данный момент все работает, причем достаточно шустро. Скрипты работают заметно шустрее, чем ранее они работали на связке apache + php + mysql. Вы видите, что в конфигурационных файлах присутствует много закомментированных строк - с ними ещё предстоит разбираться для более детальной оптимизации.

PS Так же поставил Eaccelerator - свободно-распространяемый PHP акселератор, оптимайзер и средство для кеширования динамического контента. Он увеличивает производительность PHP скриптов за счет их кеширования в скомпилированном состоянии, тем самым предотвращая их постоянную перекомпиляцию. В результате происходит увеличение скорости их выполнения. eAccelerator обычно уменьшает нагрузку на сервер и увеличивает скорость исполнения PHP кода на величину от 1 до 10 раз.

Информация об установке Eaccelerator присутвует в сети, но на данный момент она не доступна. Поэтом публикую её здесь для сохранения. Ссылка на источник: http://dedicatesupport.com (который как раз на данный момент не работает )

Итак приступим.

Выбираем последнюю версию. На данный момент последней версией является 0.9.5.2. Скачиваем и распаковываем ее.

cd /usr/local/src
wget http://bart.eaccelerator.net/source/0.9.5.2/eaccelerator-0.9.5.2.tar.bz2
bzip2 -d eaccelerator-0.9.5.2.tar.bz2
tar xvf eaccelerator-0.9.5.2.tar
cd eaccelerator-0.9.5.2

Далее необходимо проверить есть ли в нашей системе необходимые для создания модуля php пакеты.
Нам нужны:

  • apache >= 1.3,
  • mod_php >= 4.1,
  • autoconf,
  • automake,
  • libtool,
  • m4

Если производилась установка веб сервера, и php из пакетов то нам необходимо установить еще и модуль php-devel. Именно в нем находится необходимая нам программа phpize, с помощью которой и происходит компиляция модулей для php.

yum install php-devel

Далее выясняем местоположение файла phpize с помощью команды:

whereis phpize

И смотрим путь до файла. Обычно это /usr/bin/phpize.
В таком случае для компиляции модуля выполняем следующие действия:

export PHP_PREFIX="/usr"
$PHP_PREFIX/bin/phpize
./configure \
--enable-eaccelerator=shared \
--with-php-config=$PHP_PREFIX/bin/php-config
make
make install

Далее находим файл php.ini (обычно он находится в /etc/php.ini) и прописываем в нем следующие строки:

extension="eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Это для варианта использования eAccelerator как расширения php. Я использую такой подход. Есть еще вариант использования eAccelerator как расширения Zend. В таком случае прописать нужно следующие строки:

zend_extension="/usr/lib/php4/eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Далее настал черед создания каталога, котрый будет использовать eaccelerator для хранения своего кеша:

mkdir /tmp/eaccelerator
chmod 0777 /tmp/eaccelerator

Далее перезапускаем наш апач:

service httpd restart

Вы пользуетесь Drupal?