Установка nginx + php-fpm + apc для работы с magento

Алексей Саморуков, 23.10.09

В этой заметке описано, как установить magento для работы с веб сервером nginx и php-fpm. Зачем это нужно? magento предоставляет все возможности для создания функциональных и мощных систем электронной коммерции. Предоставляя максимум возможностей этот продукт достаточно требователен к ресурсам сервера. Заметка расчитана на тех, кто хочет выжать максимум производительности для своей конфигурации. Также она будет полезна и владельцам VPS, ограниченные ресурсы которых делают традиционную связку apache + php еще менее пригодной к использованию. Описываемая в статье конфигурация построена на CentOS 5.4, но может быть выполнена и на других Linux ОС или FreeBSD, с некоторыми отличиями. Также она может быть использована для построения массового magentо хостинга, так как в данном случае требования к расходу памяти становятся еще более критичными. Замена APACHE + mod_php на nginx + php-fpm позволяет существенно снизить потребление памяти, значительно повысить быстродействие при запросах статики (графика, стили и так далее) и сделать более масштабируемое решение.

Подготовка.
В качестве операционной системы для большинства наших серверов мы используем CentOS 5. С одной стороны, эта система имеет длительный срок поддержки, а с другой – достаточно консервативна, так что шансы получить проблемы при обновлениях невелики. Если у вас сервер с 4 и более гигабайтами памяти я рекомендую использовать архитектуру x86_64. CentOS 5.4 можно скачать с одного из зеркал проекта.

Установка и конфигурирование
Во время установки я рекомендую отключить все дополнительные опции и пакеты. Все, что нужно для magento мы поставим позже. Также желательно отключить firewall и selinux, как минимум до завершения установки.

Несколько слов об используемом ПО. nginx – это быстрый и крайне нетребовательный к ресурсам HTTP (и не только) сервер, который используется для раздачи статики (картинки, стили, javascript), а также позволяет работать с динамическим контентом используя FastCGI API. PHP-FPM – это улучшенная реализация интерфейса FastCGI для PHP, распространяемая в виде патча к исходникам PHP. Сервер FastCGI позволяет работать по TCP или используя локальный socket. APC – “оптимизатор” PHP, реализующий опкод кеширование для скриптов и, помимо этого, предоставляющий интерфейс для хранения данных скрипта в shared памяти. Его применение имеет смысл только в FastCGI или Apache SAPI режимах.

Репозиторий centos не содержит php-fpm. Конечно, можно самостоятельно скомпилировать PHP 5.2.11 + php-fpm, но намного более “правильный” с точки зрения удобства обновления и поддержки способ – использование репозитория. Для использования php5.2.x + fpm на наших серверах мы создали репозиторий (rpms.varien.com). В настоящий момент поддерживается CentOS/RHEL 5, архитектуры i386 и x86_64. Также нам потребуется подключить репозиторий EPEL, содержащий многие программы и библиотеки, отсутствующие в системных репозиториях CentOS/RHEL.

Подключение репозиториев:

  # rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
  # wget http://rpms.varien.com/varien-release-1-1.centos.varien.noarch.rpm
  # rpm -Uvh varien-release-1-1.centos.varien.noarch.rpm

Устанавливем нужное нам ПО:

  # yum install nginx
  # yum install php-fpm php-mysql php-gd php-mcrypt php-dom
  # yum install php-pecl-apc
  # yum install mysql-server

Включаем автостарт необходимых сервисов:

  # /sbin/chkconfig nginx on
  # /sbin/chkconfig mysqld on
  # /sbin/chkconfig php-fpm on

Конфигурируем nginx (файл /etc/nginx.conf). В данном примере магазин расположен по пути /magento/ в папке /var/www/html/magento. Поддерживается URL Rewrite (аналог конфигурации для apache mod_rewrite), для php используется PHP-FPM подключенный через unix socket.

user              nginx;
worker_processes  1;
error_log         /var/log/nginx/error.log;
pid               /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    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  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;

    # fastcgi nodes
    upstream  backend  {
        server unix:/tmp/fcgi.sock;
    }

    server {
        listen       80;
        server_name  example.local;
        root   /var/www/html;
        autoindex off;

        gzip on; # use gzip compression
        gzip_proxied any; # enable proxy for the fcgi requests
        gzip_types text/plain text/html text/css text/javascript;

        # protection (we have no .htaccess)
        location ~ (^/magento/(app/|includes/|lib/|/pkginfo/|var/|report/config.xml)|/\.svn/|/.hta.+) {
            deny all;
        }

        # handle all .php files, /downloader and /report
        location ~ (\.php|/downloader/?|/report/?)$ {
            if ($request_uri ~ /(downloader|report)$){ # no trailing /, redirecting
                rewrite  ^(.*)$ $1/ permanent;
            }
            fastcgi_index index.php;
            include /etc/nginx/fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            if (-e $request_filename) { # check if requested path exists
                fastcgi_pass backend;
            }

        }

        # handle magento
        location /magento/
        {
            # set expire headers
            if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)$") {
                expires max;
            }
            # set fastcgi settings, not allowed in the "if" block
            include /etc/nginx/fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root/magento/index.php;
            fastcgi_param SCRIPT_NAME /magento/index.php;
            # rewrite - if file not found, pass it to the backend
            if (!-f $request_filename) {
                fastcgi_pass backend;
                break;
            }
        }
    }
}

Конфигурация PHP-FPM (файл /etc/php-fpm.conf). Используется локальный socket. Наиболее важный параметр тут – max_children, его значение должно быть подобрано с учетом конфигурации (память, CPU) в процессе тестов нагрузки.

<configuration>
        <section name="global_options">
                <value name="pid_file">/var/run/php-fpm.pid</value>
                <value name="error_log">/var/log/php-fpm.log</value>
                <value name="log_level">notice</value>
                <value name="emergency_restart_threshold">10</value>
                <value name="emergency_restart_interval">1m</value>
                <value name="process_control_timeout">5s</value>
                <value name="daemonize">yes</value>
        </section>
        <workers>
                <section name="pool">
                        <value name="name">default</value>
                        <value name="listen_address">/tmp/fcgi.sock</value>
                        <value name="listen_options">
                                <value name="owner"></value>
                                <value name="group"></value>
                                <value name="mode">0666</value>
                        </value>
                        <value name="php_defines">
                        </value>
                        <value name="user">nginx</value>
                        <value name="group">nginx</value>
                        <value name="pm">
                                <value name="style">static</value>
                                <value name="max_children">10</value>
                                <value name="apache_like">
                                        <value name="StartServers">20</value>
                                        <value name="MinSpareServers">5</value>
                                        <value name="MaxSpareServers">35</value>
                                </value>
                        </value>
                        <value name="request_terminate_timeout">0s</value>
                        <value name="request_slowlog_timeout">0s</value>
                        <value name="slowlog">logs/slow.log</value>
                        <value name="rlimit_files">1024</value>
                        <value name="rlimit_core">0</value>
                        <value name="chroot"></value>
                        <value name="chdir"></value>
                        <value name="catch_workers_output">yes</value>
                        <value name="max_requests">500</value>
                        <value name="allowed_clients">127.0.0.1</value>
                        <value name="environment">
                                <value name="HOSTNAME">$HOSTNAME</value>
                                <value name="PATH">/usr/local/bin:/usr/bin:/bin</value>
                                <value name="TMP">/tmp</value>
                                <value name="TMPDIR">/tmp</value>
                                <value name="TEMP">/tmp</value>
                                <value name="OSTYPE">$OSTYPE</value>
                                <value name="MACHTYPE">$MACHTYPE</value>
                                <value name="MALLOC_CHECK_">2</value>
                        </value>
                </section>
        </workers>
</configuration>

Запускаем nginx и php-fpm:

  # /etc/init.d/php-fpm start
  # /etc/init.d/nginx start

Запускаем mysqld, и назначаем пароль для mysql рута

  # /etc/init.d/mysqld start
  # /usr/bin/mysql_secure_installation

Теперь добавляем пользователя и базу данных magento:

  # mysql --user=root -p
  mysql>  CREATE USER 'magento'@'localhost' IDENTIFIED BY 'my_password';
  mysql>  CREATE DATABASE magento;
  mysql>  GRANT ALL PRIVILEGES ON `magento`.* TO 'magento'@'%' WITH GRANT OPTION;

На этом этапе все готово для установки magento.

Установка magento
Для установки magent в консоли я использовал wiki-статью installing magento via ssh.

  1. Скачиваем magento:
    # cd /var/www/html
    # wget http://www.magentocommerce.com/downloads/assets/1.3.2.4/magento-1.3.2.4.tar.gz
    # tar -xvzf magento-1.3.2.4.tar.gz
  2. Если нам нужна тестовая база данных (sample db) – скачиваем и распаковываем ее, если нет – пропускаем этот шаг.
    # wget http://www.magentocommerce.com/downloads/assets/1.2.0/magento-sample-data-1.2.0.tar.gz
    # tar -xvzf magento-sample-data-1.2.0.tar.gz
    # mv magento-sample-data-1.2.0/media/* magento/media/
    # mysql --user=root magento -p < magento-sample-data-1.2.0/magento_sample_data_for_1.2.0.sql
  3. Назначаем корректного владельца всем файлам:
    # chown -R nginx:nginx magento

Теперь переходим к этапу настройки magento, указав в браузере адрес нашей установки, например http://example.local/magento/. Должен заработать magento installation wizard. В настройках базы данных указываем пользователя magento (и назначенный вами пароль), адрес хоста – localhost. Также следует отметить флаг “Skip Base URL validation before next step”. Дальнейшая конфигурация и использование ничем не отличается от обычных установок magento.

Дополнительная оптимизация
Прежде всего следует перенести magento cache в APC, так как файловое хранилище достаточно неєффективно, особенно при параллельных запросах. Для этого в секцию globals файла magento/app/etc/local.xml добавляем секцию cache:

    <cache>
         <backend>apc</backend>
         <prefix>MY_MAGENTO_</prefix>
    </cache>

Также рекомендуется оптимизация mysql, ip стека linux, подбор параметров APC, конфигурирование firewall, но все это уже выходит за рамки данной заметки.

Написать комментарий