Pull to refresh

Серверная оптимизация на практике

Недавно ко мне обратился мой постоянный клиент, у которого тормозил сайт moybox.ru

Сайт представляет собой площадку для общения пользователей – тут есть группы, блоги, фотогалереи, в общем полноценная социальная сеть, впридачу каждому пользователю создается почтовый ящик с разными крутыми фишками. Но сейчас не об этом. Моей задачей было посмотреть, что можно сделать с сайтом в плане улучшения быстродействия. Как оказалось, даже имея в наличии посредственный сервер с одноядерным процессором Pentium 2800 и 1 гигабайт памяти на борту, можно сделать вполне себе готовый к высоким нагрузкам проект.

Фронтенд – бэкенд


Беглый взгляд обнаружил, что основной функционал сайта составляет InstantCMS. Платформа стандартная LAMP, дистрибутив Ubuntu 10.10. Как это обычно бывает, веб-сервером служил Apache2. Первой идеей стало установка легкого фронтенда nginx перед Apache. Не так давно вышла версия nginx 1.0.0, ее я и поставил на сервер:
wget http://sysoev.ru/nginx/nginx-1.0.0.tar.gz
tar xvzf nginx-1.0.0.tar.gz
cd nginx-1.0.0
./configure --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-client-body-temp-path=/var/lib/nginx/body --http-log-path=/var/log/nginx/access.log --http-proxy-temp-path=/var/lib/nginx/proxy --lock-path=/var/lock/nginx.lock --pid-path=/var/run/nginx.pid --with-http_gzip_static_module --with-http_stub_status_module --with-http_realip_module --with-http_ssl_module
make install
strip /usr/local/nginx/sbin/nginx


Вот часть конфига nginx, описывающая виртуальный хост moybox.ru. В Ubuntu этот файлик кладется в /etc/nginx/sites-enabled.
server {
listen 0.0.0.0:80;
server_name moybox.ru www.moybox.ru;

location / {
    proxy_pass http://127.0.0.1:81/;
}
location ~* \.(jpg|gif|png|css|js)$ {
    root /www/site;
}
}

Вот статистика до и после установки nginx, которая поражает (точнее, ужасает скорость Apache в данном случае):
image
Clients 10 20
Delay (min) 0.83 1.6

При использовании nginx:
image
Clients 10 20 30 40 50
Delay (ms) 659 686 684 727 819

Как видно, Apache еле шевелился даже на небольшом количестве клиентов. Неудивительно, такая у него архитектура. Использование nginx уменьшило среднее время доступа с 1 минуты до 1 секунды, причем уже для 50 клиентов. В случае Apache дело не дошло даже до 30 клиентов.

Отдельные тесты показали, что увеличивать количество рабочих процессов – воркеров nginx (1) и apache (5) не имеет смысла. Средняя скорость доступа практически не меняется вплоть до 50 клиентов, а отдавать бесценную память расплодившимся процессам apache зазря не очень хочется.

gzip_static и оптимизация файлов


С этим разобрались, но естественно, это еще не все пути оптимизации. Теперь посмотрим на размер главной страницы сайта с помощью другого инструмента того же сайта – Page Analyzer, сгруппируем файлы главной страницы по размеру:
image
Total downloaded data: 290.47 KiB

Видим, что значительную часть занимают CSS, javascript и всякие фоновые картинки. С последним ничего хитрого нет. Травку в нижней части сайта в формате png конвертируем в формат jpeg и получаем 7К из исходных 44К. Изображение письма преобразуем в gif со степенью постеризации 64 и прозрачным фоном, получаем 8К из исходных 16К, практически без потери качества “на глаз”.

Теперь перейдем к оптимизации файлов css/js и собственно html, ведь они одни составляют 130К – около половины веса страницы.

В nginx есть такая замечательная директива gzip, которая позволяет отдавать браузеру сжатую в gzip версию файла. Причем если включена еще и gzip_static, то, к примеру, вместо filename.txt будет отдаваться лежащий рядом заранее заготовленный файл filename.txt.gz. То есть, таким образом экономится время на сжатие файла сервером – один раз сжал и далее его только отдавать. Нужно только следить за актуальностью сжатого файла по отношению к оригиналу.

Наибольший размер имеют styles.css и jquery.js, их и будем оптимизировать. Для их сжатия я использую yui-compressor, вот так (здесь также я решил сжать фоновый файл bg.jpg):
yui-compressor styles.css | gzip -c -5 > styles.css.gz
yui-compressor jquery.css | gzip -c -5 > jquery.css.gz
gzip bg.jpg > bg.jpg.gz

По многочисленным рекомендациям, ставить уровень сжатия GZIP выше 5 не стоит – только тратится процессорное время, а улучшение сжатия практически незаметно. Другие css- и js-файлы, а также HTML как результат работы InstantCMS, будем сжимать на лету и отдавать по gzip. А мелкие файлы меньше 1 килобайта сжимать вообще не будем.
Вот полученный конфиг nginx:
user www-data;
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;

access_log /var/log/nginx/access.log;

sendfile on;
tcp_nopush on;
keepalive_timeout 65;
tcp_nodelay on;

gzip on;
gzip_static on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_types application/x-javascript text/css;
gzip_min_length 1024;

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}

Вот результат проделанных махинаций, весьма впечатляет:
image
Полный размер главной страницы составил 93.13 KiB, что меньше прежнего размера в 3 раза (!).

Оптимизация PHP


Еще можно ускорить выполнение php-скриптов за счет кеширования байткода в оперативной памяти. Установим eaccelerator, также из исходников:
wget http://bart.eaccelerator.net/source/0.9.6.1/eaccelerator-0.9.6.1.tar.bz2
tar xvjf eaccelerator-0.9.6.1.tar.bz2
cd eaccelerator-0.9.6.1
apt-get install php5-dev
phpize
./configure
make install

Прописываем в /etc/php5/apache2/conf.d/eaccelerator.ini следующие параметры:
extension="eaccelerator.so"
eaccelerator.shm_size="64"
eaccelerator.cache_dir="/var/cache/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="3600"
eaccelerator.shm_prune_period="1800"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Создаем каталог для кеша:
mkdir -m 0777 /var/cache/eaccelerator
и перезапускаем веб-сервер:
/etc/init.d/apache2 restart
Если апач откажется запускаться с вот такой ошибкой:
eAccelerator: Could not allocate 67108864 bytes, the maximum size the kernel allows is 33554432 bytes. Lower the amount of memory request or increase the limit in /proc/sys/kernel/shmmax.

Тогда нужно либо уменьшить запрашиваемый объем памяти с 64 мегабайт на поменьше, либо повысить порог shmmax до требуемого значения:
echo 67108864 > /proc/sys/kernel/shmmax
echo kernel.shmmax = 67108864 >> /etc/sysctl.conf

После этого наши php-скрипты должны кешироваться в памяти, что можно наблюдать, к примеру, в выводе функции phpinfo:
image

Вот результат, которого удалось добиться на данном этапе:
image
Clients 10 20 30 40 50
Delay (ms) 410 415 437 416 423

И второй график – время полной загрузки страницы (с учетом всех картинок, скриптов и т.п.):
image

Эта история – хороший пример того, что может происходить, когда в каком-то проекте никто не задумывается о производительности, и оставляет все настройки “по умолчанию”. Как показала практика, даже простая установка nginx как фронтенда к апачу ускоряет сайт в десятки раз.
4
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.