пятница, 18 июля 2014 г.

Varnish, nginx, php-fpm, mysql, apc, wordpress на Centos 6

Добрый день.

Решил поставить небольшую связку на своем VPS сервере. Что бы посмотреть результаты и скорость работы сайта. Основные компоненты: 

nginx [engine x] — это HTTP-сервер и обратный прокси-сервер, а также почтовый прокси-сервер, написанный Игорем Сысоевым. Уже длительное время он обслуживает серверы многих высоконагруженных российских сайтов, таких как ЯндексMail.RuВКонтакте и Рамблер. Согласно статистике Netcraft nginx обслуживал или проксировал 19.21% самых нагруженных сайтов в июне 2014 года. Вот некоторые примеры успешного внедрения nginx (тексты на английском языке): NetflixWordpress.comFastMail.FM.

MySQL (МФА: [maɪ ˌɛskjuːˈɛl]) — свободная реляционная система управления базами данных. Разработку и поддержку MySQL осуществляет корпорация Oracle, получившая права на торговую марку вместе с поглощённой Sun Microsystems, которая ранее приобрела шведскую компанию MySQL AB. Продукт распространяется как под GNU General Public License, так и под собственной коммерческой лицензией. Помимо этого, разработчики создают функциональность по заказу лицензионных пользователей. Именно благодаря такому заказу почти в самых ранних версиях появился механизм репликации.

PHP-FPM (FastCGI Process Manager) - PHP реализация FastCGI.

Varnish - HTTP ускоритель предназначен для тяжелых динамических веб-сайтов. В отличие от других ускорителей Интернета, таких как Squid, который начал существовать в качестве кэш со стороны клиента, или Apache и Nginx, которые в первую очередь web сервера, Varnish был разработан в качестве ускорителя HTTP. Varnish сосредоточен исключительно на HTTP, в отличие от других прокси-серверов, которые часто поддерживают FTP, SMTP и другие сетевые протоколы.

The Alternative PHP Cache — бесплатный и открытый opcode кэшер для PHP. Он был задуман, как бесплатный, открытый и стабильный фреймворк для кэширования и оптимизации исходного кода PHP, так же возможно кэширование пользовательских данных.

Общая схема работы примерно такая:




Ставим MySQL

Ставим сам MySQL сервер:
# yum install mysql-server

Запускаем сервис:
# /etc/init.d/mysqld start

Установим пароль для суперпользователя root:
# /usr/bin/mysqladmin -u root password 'password'
или
# /usr/bin/mysql_secure_installation

Зададим запуск сервиса во время старта системы:
# chkconfig --levels 2345 mysqld on

Поставим расширение PHP для работы с MySQL:
# yum install php-mysql

Отредактируем файл конфигурации MySQL сервера (это самый базовый конфиг, его можно оптимизировать и улучшать по своим потребностям):
# vim /etc/my.cnf
# cat /etc/my.cnf 
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
skip-innodb
query_cache_size = 8M
thread_cache_size = 4
query_cache_limit = 4M
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

Перезапустим сервис, что бы MySQL перечитал конфигурационный файл:
# /etc/init.d/mysql restart

Ставим nginx

Подключаем репозиторий nginx:
# vim /etc/yum.repos.d/nginx.repo
# cat /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

Поставим nginx:
# yum install nginx

Создадим файл конфигурации для домена (в моем случае asidorov.name):
# vim /etc/nginx/conf.d/asidorov.name.conf
# cat /etc/nginx/conf.d/asidorov.name.conf 
server {
    listen       127.0.0.1:8080; # Слушаем 8080 порт на localhost
    server_name  asidorov.name; # Имя сервера
    set_real_ip_from 127.0.0.1; Задаёт доверенные адреса, которые передают верный адрес для замены.
    real_ip_header X-Forwarded-For; Задаёт поле заголовка запроса, в котором передаётся адрес для замены.
    sendfile on; # Разрешает использование sendfile()
    tcp_nopush on; # Разрешает использование параметра сокета TCP_CORK в Linux
    tcp_nodelay on; # Разрешает использование параметра TCP_NODELAY
    keepalive_timeout 20; #задаёт таймаут, в течение которого keep-alive соединение с клиентом не будет закрыто со стороны сервера
    client_max_body_size 15m;  максимально допустимый размер тела запроса клиента, указываемый в поле “Content-Length” заголовка запроса
    client_body_timeout 60; таймаут при чтении тела запроса клиента
    client_header_timeout 60; # таймаут при чтении заголовков запроса клиента
    client_body_buffer_size 1K; размер буфера для чтения тела запроса клиента
    client_header_buffer_size 1K; # размер буфера для чтения заголовков запроса клиента
    large_client_header_buffers 4 8K; максимальное число и размер буферов для чтения большого заголовка запроса клиента
    send_timeout 60; таймаут при передаче ответа клиенту
    reset_timedout_connection on; # Разрешает сброс соединений по таймауту
    types_hash_max_size 2048; # Задает максимальный размер хэш-таблиц типов
    server_tokens off; запрещает выдавать версию nginx’а 
    gzip on; # разрешает сжатие ответа методом gzip
    gzip_disable "msie6"; Запрещает сжатие ответа методом gzip для запросов из Internet Explorer
    gzip_vary on; # Разрешает выдавать в ответе поле заголовка “Vary: Accept-Encoding”
    gzip_proxied any; разрешает сжатие для всех проксированных запросов
    gzip_comp_level 6; # Задает уровень сжатия
    gzip_buffers 16 8k;Задаёт число и размер буферов, в которые будет сжиматься ответ
    gzip_http_version 1.1;Устанавливает минимальную HTTP-версию запроса, необходимую для сжатия ответа
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; # Включает gzip для заданных mime-типов
    root /var/www/asidorov.name; # где лежит наш сайт
    index index.php index.html index.htm; # порядок индексных страниц
    expires 86400s; # дефолтное время кеширования (24 часа)
    add_header Pragma public; # Добавляет хедеры
    add_header Cache-Control "max-age=86400, public, must-revalidate, proxy-revalidate";

    location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    location = /50x.html {
root /usr/share/nginx/html;
    }
    location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
    }
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
        access_log off;
add_header Pragma public;
add_header Cache-Control "max-age=31536000, public";
    }
    location = /favicon.ico {
log_not_found off;
access_log off;
    }
    location = /robots.txt {
allow all;
log_not_found off;
access_log off;
    }
}

Уберем дефолтный конфиг от греха подальше:
# mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default 

Перезапустим nginx:
# /etc/init.d/nginx restart

Ставим PHP-FPM

# yum install php-fpm

Приведем конфиг к такому виду:
# cat /etc/php-fpm.d/www.conf 
[www]
listen = /var/run/php-fpm/php-fpm.sock
listen.allowed_clients = 127.0.0.1
listen.owner = apache
listen.group = apache
listen.mode = 0666
user = apache
group = apache
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 200
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session

Запуск системы при старте системы:
# chkconfig --levels 2345 php-fpm on

Перезапустим php-fpm:
# /etc/init.d/php-fpm restart

Ставим APC

# yum install php-pecl-apc


Ставим Wordpress

Перейдем во временную директорию:
# cd /tmp/

Скачаем последнюю версию Wordpress:
# wget http://wordpress.org/latest.tar.gz

Разархивируем архив с Wordpress:
# tar xvf latest.tar.gz 

Создаем базу для Wordpress'a:
# mysql -uroot -p
mysql> CREATE DATABASE wordpress;
mysql> CREATE USER wp@localhost;
mysql> GRANT ALL PRIVILEGES ON wordpress.* TO wp@localhost IDENTIFIED BY 'wpassword';
mysql> FLUSH PRIVILEGES;
mysql> quit

Подредактируем конфиг Wordpress'a:
# cp /tmp/wordpress/wp-config-sample.php /tmp/wordpress/wp-config.php
# vim /tmp/wordpress/wp-config.php 
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wp');
/** MySQL database password */
define('DB_PASSWORD', 'wpassword');
/** MySQL hostname */
define('DB_HOST', 'localhost');

Создадим директорию, где будет лежать наш сайт:
# mkdir /var/www/asidorov.name

Скопируем файлы сайта в новую директорию:
# cp -r /tmp/wordpress/* /var/www/asidorov.name/

Поменяем права на файлы:
# chown -R apache:apache /var/www/asidorov.name

Переходим по адресу asidorov.name и устанавливаем Wordpress.

Так же очень советую установить такие плагины как: W3 Total Cache и Better Wordpress Minify


Ставим Varnish

Подключим репозиторий с Varnish:
# rpm --nosignature -i http://repo.varnish-cache.org/redhat/varnish-3.0/el6/noarch/varnish-release/varnish-release-3.0-1.el6.noarch.rpm

Поставим Varnish:
# yum install varnish

Зададим автозапуск сервиса при старте системы:
# chkconfig --levels 2345 varnish on

Приведем конфиг Varnish'a к такому виду:
# vim /etc/sysconfig/varnish 
# cat /etc/sysconfig/varnish 
NFILES=131072
MEMLOCK=82000
NPROCS="unlimited"
RELOAD_VCL=1
VARNISH_VCL_CONF=/etc/varnish/default.vcl
VARNISH_LISTEN_PORT=80
VARNISH_ADMIN_LISTEN_ADDRESS=127.0.0.1
VARNISH_ADMIN_LISTEN_PORT=6082
VARNISH_SECRET_FILE=/etc/varnish/secret
VARNISH_MIN_THREADS=50
VARNISH_MAX_THREADS=1000
VARNISH_THREAD_TIMEOUT=120
VARNISH_STORAGE_FILE=/var/lib/varnish/varnish_storage.bin
VARNISH_STORAGE_SIZE=1G
VARNISH_STORAGE="file,${VARNISH_STORAGE_FILE},${VARNISH_STORAGE_SIZE}"
VARNISH_TTL=120
DAEMON_OPTS="-a :${VARNISH_LISTEN_PORT} \
             -f ${VARNISH_VCL_CONF} \
             -T ${VARNISH_ADMIN_LISTEN_ADDRESS}:${VARNISH_ADMIN_LISTEN_PORT} \
             -t ${VARNISH_TTL} \
             -w ${VARNISH_MIN_THREADS},${VARNISH_MAX_THREADS},${VARNISH_THREAD_TIMEOUT} \
             -u varnish -g varnish \
    -p thread_pools=2 \
    -p thread_pool_min=25 \
    -p thread_pool_max=250 \
    -p thread_pool_add_delay=2 \
    -p session_linger=50 \
    -p cli_timeout=40 \
    -p sess_workspace=262144 \
             -S ${VARNISH_SECRET_FILE} \
             -s ${VARNISH_STORAGE}"

Так же поступим с конфигом:
# vim /etc/varnish/default.vcl
# cat /etc/varnish/default.vcl 
# cat /etc/varnish/default.vcl  
backend default {
  .host = "127.0.0.1";
  .port = "8080";
}
acl purge {
"127.0.0.1";
}
sub vcl_recv {
if (req.request == "PURGE") {
if (!client.ip ~ purge) {
error 405 "Not allowed.";
}
ban("req.url ~ ^" + req.url + " && req.http.host == " + req.http.host);
return(lookup);
}
set req.http.X-Forwarded-For = client.ip;
if (req.http.Accept-Encoding) {
if (req.url ~ "\.(jpg|png|gif|gz|tgz|bz2|lzma|tbz)(\?.*|)$") {
remove req.http.Accept-Encoding;
        } elsif (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        } elsif (req.http.Accept-Encoding ~ "deflate") {
            set    req.http.Accept-Encoding = "deflate";
        } else {
            remove req.http.Accept-Encoding;
        }
    }
if (req.url ~ "^/[^?]+\.(gif|jpg|jpeg|swf|css|js|txt|flv|mp3|mp4|pdf|ico|png|gz|zip|lzma|bz2|tgz|tbz)(\?.*|)$") {
       unset req.http.cookie;
       set req.url = regsub(req.url, "\?.*$", "");
    }
   if (req.url ~ "((wp-(login|admin|comments-post.php|cron.php))|login|timthumb|wrdp_files)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
        return (pass);
    } else {
        if ( !(req.http.cookie ~ "wpoven-no-cache") ) {
            unset req.http.cookie;
        }
    }
}

sub vcl_hit {
   if (req.request == "PURGE") {
        purge;
        error 200 "Purged";
    }
}
sub vcl_miss {
       if (req.request == "PURGE") {
        if (!client.ip ~ purge) {
        error 405 "Not allowed.";
        }
        ban("req.url ~ "+req.url);
        error 200 "Purged";
        }

    if (req.request == "PURGE") {
        purge;
        error 404 "Purged varients";
    }
}
sub vcl_fetch {
   if (req.url ~ "(wp-(login|admin|comments-post.php|cron.php))|login" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") {
        return (deliver);
    } else {
        if ( beresp.ttl > 0s && !(beresp.http.set-cookie ~ "wpoven-no-cache") ) {
            unset beresp.http.set-cookie;
        }
    }
}
sub vcl_deliver {
   unset resp.http.Server;
    unset resp.http.X-Powered-By;
    unset resp.http.x-backend;
    unset resp.http.Via;
    unset resp.http.X-Varnish;
}

Перезапустим Varnish:
# /etc/init.d/varnish restart



Вот такие результаты я получил в итоге:

А вот результаты работы ab:
$ ab -c 100 -n 1500 http://asidorov.name/
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking asidorov.name (be patient)
Completed 150 requests
Completed 300 requests
Completed 450 requests
Completed 600 requests
Completed 750 requests
Completed 900 requests
Completed 1050 requests
Completed 1200 requests
Completed 1350 requests
Completed 1500 requests
Finished 1500 requests


Server Software:        
Server Hostname:        asidorov.name
Server Port:            80

Document Path:          /
Document Length:        21009 bytes

Concurrency Level:      100
Time taken for tests:   129.756 seconds
Complete requests:      1500
Failed requests:        1
   (Connect: 0, Receive: 0, Length: 1, Exceptions: 0)
Write errors:           0
Total transferred:      32068107 bytes
HTML transferred:       31492491 bytes
Requests per second:    11.56 [#/sec] (mean)
Time per request:       8650.415 [ms] (mean)
Time per request:       86.504 [ms] (mean, across all concurrent requests)
Transfer rate:          241.35 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0 2153 8454.8     90   63194
Processing:    63  264 342.5    182    6253
Waiting:       31   92 161.3     85    3294
Total:         94 2417 8413.7    296   63258

Percentage of the requests served within a certain time (ms)
  50%    296
  66%    396
  75%    747
  80%    913
  90%   3097
  95%  15119
  98%  31168
  99%  63202
 100%  63258 (longest request)

Тут видно, что я задал 100 параллельных запросов, при этом среднее время загрузки страницы 86 мс (что ооочень хорошо). При этом на моем VPS использовалось всего 300 Мб оперативной памяти.


Полезные ссылки

https://www.digitalocean.com/community/tutorials/how-to-install-linux-nginx-mysql-php-lemp-stack-on-centos-6
http://www.garron.me/en/linux/nginx-php-fpm-mysql-apc-varnish-wordpress-cache-performance.html
http://wplifeguard.com/install-linux-nginx-php-fpm-mysql-lemp-wordpress-on-ubuntu/
http://nls.io/optimize-nginx-and-php-fpm-max_children/
http://www.namhuy.net/2372/how-to-install-and-configure-varnish-with-apache-on-centos-6.html
http://www.syntaxheaven.com/configure-nginx-php-fpm-apc-varnish-for-wordpress/

Комментариев нет:

Отправить комментарий