Недавно ко мне обратился мой постоянный клиент, у которого тормозил сайт moybox.ru
Сайт представляет собой площадку для общения пользователей – тут есть группы, блоги, фотогалереи, в общем полноценная социальная сеть, впридачу каждому пользователю создается почтовый ящик с разными крутыми фишками. Но сейчас не об этом. Моей задачей было посмотреть, что можно сделать с сайтом в плане улучшения быстродействия. Как оказалось, даже имея в наличии посредственный сервер с одноядерным процессором Pentium 2800 и 1 гигабайт памяти на борту, можно сделать вполне себе готовый к высоким нагрузкам проект.
Беглый взгляд обнаружил, что основной функционал сайта составляет InstantCMS. Платформа стандартная LAMP, дистрибутив Ubuntu 10.10. Как это обычно бывает, веб-сервером служил Apache2. Первой идеей стало установка легкого фронтенда nginx перед Apache. Не так давно вышла версия nginx 1.0.0, ее я и поставил на сервер:
Вот часть конфига nginx, описывающая виртуальный хост moybox.ru. В Ubuntu этот файлик кладется в /etc/nginx/sites-enabled.
Вот статистика до и после установки nginx, которая поражает (точнее, ужасает скорость Apache в данном случае):
При использовании nginx:
Как видно, Apache еле шевелился даже на небольшом количестве клиентов. Неудивительно, такая у него архитектура. Использование nginx уменьшило среднее время доступа с 1 минуты до 1 секунды, причем уже для 50 клиентов. В случае Apache дело не дошло даже до 30 клиентов.
Отдельные тесты показали, что увеличивать количество рабочих процессов – воркеров nginx (1) и apache (5) не имеет смысла. Средняя скорость доступа практически не меняется вплоть до 50 клиентов, а отдавать бесценную память расплодившимся процессам apache зазря не очень хочется.
С этим разобрались, но естественно, это еще не все пути оптимизации. Теперь посмотрим на размер главной страницы сайта с помощью другого инструмента того же сайта – Page Analyzer, сгруппируем файлы главной страницы по размеру:
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):
По многочисленным рекомендациям, ставить уровень сжатия GZIP выше 5 не стоит – только тратится процессорное время, а улучшение сжатия практически незаметно. Другие css- и js-файлы, а также HTML как результат работы InstantCMS, будем сжимать на лету и отдавать по gzip. А мелкие файлы меньше 1 килобайта сжимать вообще не будем.
Вот полученный конфиг nginx:
Вот результат проделанных махинаций, весьма впечатляет:
Полный размер главной страницы составил 93.13 KiB, что меньше прежнего размера в 3 раза (!).
Еще можно ускорить выполнение php-скриптов за счет кеширования байткода в оперативной памяти. Установим eaccelerator, также из исходников:
Прописываем в /etc/php5/apache2/conf.d/eaccelerator.ini следующие параметры:
Создаем каталог для кеша:
и перезапускаем веб-сервер:
Если апач откажется запускаться с вот такой ошибкой:
Тогда нужно либо уменьшить запрашиваемый объем памяти с 64 мегабайт на поменьше, либо повысить порог
После этого наши php-скрипты должны кешироваться в памяти, что можно наблюдать, к примеру, в выводе функции phpinfo:
Вот результат, которого удалось добиться на данном этапе:
И второй график – время полной загрузки страницы (с учетом всех картинок, скриптов и т.п.):
Эта история – хороший пример того, что может происходить, когда в каком-то проекте никто не задумывается о производительности, и оставляет все настройки “по умолчанию”. Как показала практика, даже простая установка nginx как фронтенда к апачу ускоряет сайт в десятки раз.
4
Сайт представляет собой площадку для общения пользователей – тут есть группы, блоги, фотогалереи, в общем полноценная социальная сеть, впридачу каждому пользователю создается почтовый ящик с разными крутыми фишками. Но сейчас не об этом. Моей задачей было посмотреть, что можно сделать с сайтом в плане улучшения быстродействия. Как оказалось, даже имея в наличии посредственный сервер с одноядерным процессором 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 в данном случае):
Clients | 10 | 20 |
Delay (min) | 0.83 | 1.6 |
При использовании nginx:
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, сгруппируем файлы главной страницы по размеру:
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/*;
}
Вот результат проделанных махинаций, весьма впечатляет:
Полный размер главной страницы составил 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:
Вот результат, которого удалось добиться на данном этапе:
Clients | 10 | 20 | 30 | 40 | 50 |
Delay (ms) | 410 | 415 | 437 | 416 | 423 |
И второй график – время полной загрузки страницы (с учетом всех картинок, скриптов и т.п.):
Эта история – хороший пример того, что может происходить, когда в каком-то проекте никто не задумывается о производительности, и оставляет все настройки “по умолчанию”. Как показала практика, даже простая установка nginx как фронтенда к апачу ускоряет сайт в десятки раз.
4