Після покупки VPS сервера виникає маса проблем. Потрібно вибрати веб-сервер, фтп-сервер, поштовий сервер. Потрібно продумати принципи організації роботи веб-сервера з окремими модулями.
Проблеми починають проявляти себе безпосередньо в роботі. Те пам'яті надто багато витрачається, то процесор працює постійно на максимумі, то починає позначатися низька швидкість роботи жорсткого диска, то ще що-небудь.
Ось тут і настає момент необхідності оптимізації. Коли встановлені програми починають налаштовувати, тестувати, знову налаштовувати.
Вступна
Нагадаю лише, що я використовую VPS від linode.com, мінімальний тариф з 512 мегабайтами оперативної пам'яті і 4-х ядерних процесором. Встановлена операційна система Ubuntu 10.04. Як веб-сервера використовується Nginx + php5-fpm + XCache.
Я проводив вже стрес-тест продуктивності, результати описував в статті Тест продуктивності VPS сервера . І на той момент, сервер показав результат в 14.15 запиту / сек. Для того, щоб витримати відвідуваність мого сайту цього результату цілком достатньо, але стала відчуватися інша проблема. У навантаженні надмірно витрачалася оперативна пам'ять.
500 запитів цілком вистачало для того, щоб процеси php заповнювали всю оперативну пам'ять, витісняючи попутно все буфери і кеши, а потім і весь своп. Продовження подібної стресового навантаження могли просто упустити сервер. І це мене дуже сильно стурбувало.
Я просто не розумів, чому php5-fpm починає так сильно витрачати оперативну пам'ять. Як взагалі в подібних умовах живуть інші проекти?
Намагався змінювати число процесів і nginx і php5-fpm, зменшуючи до мінімуму, проте це давало тільки зайві хвилини роботи, але не рятувало від самої проблеми. Два процесу php5-fpm точно так же заповнювали весь простір виділеної пам'яті, як і всі вісім. Довелося на час залишити мінімальне число процесів, для того, щоб довше витримувати навантаження і шукати рішення.
Ще трохи врятувало становище зміна налаштувань php5-fpm. У файлі /etc/php5/fpm/php5-fpm.conf змінив наступні значення:
emergency_restart_threshold = 10 emergency_restart_interval = 1m process_control_timeout = 5s pm.max_requests = 500
Стало трохи легше. Тепер через певний час процеси php5-fpm стали перезапускатися, вивільняючи зайняту пам'ять. Але витоку тривали.
Memcached
Сьогодні вирішив спробувати в роботі модуль memcached. Перед цим довелося думати і вирішувати, чи варто це робити, тому що на додатковий модуль буде потрібно виділити певну кількість оперативної пам'яті, а її і так катастрофічно не вистачало. Вирішив все таки ризикнути і подивитися, що вийде. Все одно на сайті навантаження не велика. Встановлюємо і запускаємо:
# Apt-get install memcached php5-memcache # /etc/init.d/memcached start
Тепер необхідно прописати використання memcached в php5-fpm, для цього змінюємо файл /etc/php5/fpm/php.ini і в самий початок, після директиви [PHP] прописуємо:
Тепер перезапускаємо php:
# /Etc/init.d/php5-fpm restart
І дивимося, чи з'явився блок memcache у висновку функції phpinfo (), якщо з'явилося, значить все нормально. Єдино, перед самим запуском memcached я ще змінив його настройки, збільшивши активну пам'ять з 16 мегабайт до 64.
Подальший стрес-тест кинув мене в подив! Продуктивність не змінилася, але витоку пам'яті просто зникли. Припинився цей дикий витрата оперативної пам'яті.
Для того, щоб подивитися, скільки пам'яті використовується в даний момент часу сам memcached, використовував команду:
ps -e | grep 'memcached' | awk '{print $ 0} {sum + = $ 1} END {print "\ nMemory usage for memcached:", sum / 1024, "MB \ n"}'
Результат - трохи більше 6 мегабайтів оперативної пам'яті. Тобто 64 мегабайта, що я виділив, з лишком вистачає на все.
тести
Провів ряд тестів, для того, щоб відстежити, яке число процесів nginx і php5-fpm є оптимальним для використання на VPS від Linode на мінімальному тарифі. Для цього, як і в минулий раз, використовував утиліту ab з поставки веб-сервера apache. Запускав наступним чином:
ab -n 1000 -n 50 http://domain.ru/index.php
Збільшив число запитів до 1000 і збільшив число одночасних запитів до сервера до 50. Мене цікавив витрата оперативної пам'яті і природно, продуктивність веб-сервера, тобто скільки запитів він зможе обробляти в секунду.
Для цього я зраджував число процесів nginx, потім число процесів php5-fpm і спостерігав за показаннями утиліти htop.
Перший тест проводив з тим же числом процесів, що використовував до установки memcached.
2 nginx і 2 php5-fpm:
Concurrency Level: 50 Time taken for tests: 89.755 seconds Complete requests 1000 Failed requests: 0 Write errors: 0 Non-2xx responses 1000 Total transferred: 283000 bytes HTML transferred: 0 bytes Requests per second: 11.14 [# / sec] ( mean) Time per request: 4487.736 [ms] (mean) Time per request: 89.755 [ms] (mean, across all concurrent requests) Transfer rate: 3.08 [Kbytes / sec] received Connection Times (ms) min mean [+/- sd] median max Connect: 0 0 0.7 0 4 Processing: 1656 4379 320.6 4390 6135 Waiting: 1656 4379 320.6 4390 6135 Total: 1661 4379 320.3 4390 6137
Максимальні витрати пам'яті при цьому 123Mb. Вільної пам'яті ще багато, а ось продуктивність невисока, помітно, що в роботі беруть участь тільки два з чотирьох виділених ядер. Збільшуємо число php процесів до 4.
2 nginx і 4 php5-fpm:
Concurrency Level: 50 Time taken for tests: 46.838 seconds Complete requests 1000 Failed requests: 0 Write errors: 0 Non-2xx responses 1000 Total transferred: 283000 bytes HTML transferred: 0 bytes Requests per second: 21.35 [# / sec] ( mean) Time per request: 2341.875 [ms] (mean) Time per request: 46.838 [ms] (mean, across all concurrent requests) Transfer rate: 5.90 [Kbytes / sec] received Connection Times (ms) min mean [+/- sd] median max Connect: 0 0 0.7 0 5 Processing: 401 2287 225.4 2286 3039 Waiting: 401 2286 225.4 2286 3039 Total: 406 2287 225.0 2286 3041
Максимальні витрати пам'яті в даному випадку 157Mb. Кількість оброблюваних запитів зросла майже в два рази. Не погано. Пробуємо збільшити число процесів nginx, по суті має зрости значення максимальної кількості одночасних з'єднань.
4 nginx і 4 php5-fpm:
Concurrency Level: 50 Time taken for tests: 45.951 seconds Complete requests 1000 Failed requests: 0 Write errors: 0 Non-2xx responses 1000 Total transferred: 283000 bytes HTML transferred: 0 bytes Requests per second: 21.76 [# / sec] ( mean) Time per request: 2297.534 [ms] (mean) Time per request: 45.951 [ms] (mean, across all concurrent requests) Transfer rate: 6.01 [Kbytes / sec] received Connection Times (ms) min mean [+/- sd] median max Connect: 0 0 0.7 0 4 Processing: 494 2239 214.0 2245 2988 Waiting: 494 2239 214.0 2245 2988 Total: 498 2240 213.6 2245 2990
Максимальні витрати пам'яті в цьому випадку 154Mb. Що навіть трохи менше ніж в попередньому випадку, що трохи дивно. Однак число запитів, яке обробляє сервер кожну секунду, залишилося незмінним. Чи має тоді сенс тримати запущеними кілька nginx ??
1 nginx і 4 php5-fpm:
Concurrency Level: 50 Time taken for tests: 46.050 seconds Complete requests 1000 Failed requests: 0 Write errors: 0 Non-2xx responses 1000 Total transferred: 283000 bytes HTML transferred: 0 bytes Requests per second: 21.72 [# / sec] ( mean) Time per request: 2302.504 [ms] (mean) Time per request: 46.050 [ms] (mean, across all concurrent requests) Transfer rate: 6.00 [Kbytes / sec] received Connection Times (ms) min mean [+/- sd] median max Connect: 0 0 0.7 0 4 Processing: 527 2246 201.0 2260 2968 Waiting: 526 2246 201.0 2260 2968 Total: 531 2246 200.6 2260 2969
Максимальні витрати пам'яті 151Mb. Як бачимо, на витрату пам'яті це впливає мало, і на число оброблюваних запитів теж. Поки не бачу сенсу запускати додаткові процеси nginx.
Стало цікаво, а що буде, якщо поставити число запущених php-процесів більше, ніж число ядер ??
1 nginx і 8 php5-fpm:
220 Mb max Concurrency Level: 50 Time taken for tests: 47.617 seconds Complete requests 1000 Failed requests: 0 Write errors: 0 Non-2xx responses 1000 Total transferred: 283000 bytes HTML transferred: 0 bytes Requests per second: 21.00 [# / sec] (mean) Time per request: 2380.835 [ms] (mean) Time per request: 47.617 [ms] (mean, across all concurrent requests) Transfer rate: 5.80 [Kbytes / sec] received Connection Times (ms) min mean [ +/- sd] median max Connect: 0 0 1.2 0 7 Processing: 544 2331 202.2 2336 3307 Waiting: 544 2331 202.2 2336 3307 Total: 549 2331 201.9 2336 3312
Максимальні витрати пам'яті склав 220Mb. Кількість запитів навіть кілька впало, зміни немає. Тобто фактично збільшувати число процесів php вище 4 для мого сервера навряд чи варто.
оптимізація XCache
У всіх тестах використовувалося розширення WP Super Cache. При тесті, природно були задіяні кешовані сторінки, що досить непогано піднімало швидкість віддачі сторінки і зменшувало час її генерації. Адміністратор за замовчуванням працює з некешірованнимі сторінками і на швидкість впливає тільки продуктивність PHP-інтерпретатора. Хоча і був встановлений модуль php5-xcache, в адмінці били помітні якісь гальма.
До цього моменту використовував настройки XCache за замовчуванням. вирішив трохи повозитися і пошукати варіанти конфігурацій в мережі інтернет. Змінив лише кілька налаштувань у файлі /etc/php5/conf.d/xcache.ini:
xcache.size = 64M xcache.count = 4 xcache.var_size = 64M
Значення xcache.size збільшив з 16 до 64 мегабайт. Параметр xcache.count вказує на кількість використовуваних на машині ядер, встановив в 4. І xcache.var_size змінив з 0 на 64 мегабайта.
Після перезапуску php5-fpm, і Адаменко стала більш чуйною!
висновки
Установки використовуваних програм рідко бувають оптимальними за замовчуванням. Потрібно кожен встановлений сервіс протестувати і визначити оптимальні настройки для кожного конкретного випадку.
За допомогою тестів мені вдалося значно знизити споживання оперативної пам'яті. І при цьому досягти показників оброблюваних запитів до сервера до 21.72. Що вище, ніж навіть у налаштованого шаред-хостингу, що я використовував раніше.
Зовсім не очікував, що установка memcached дозволить мені вирішити проблему з витоками пам'яті. Тепер же настійно рекомендую використовувати цей модуль PHP на серверах, що розміщують в собі WordPress.
Після проведених тестів загорівся довести обробляється число запитів до 100 в секунду. Правда розумію, що саме зараз це навряд чи можливо, тому що під час тестів все впиралося в продуктивність процесора. Буду шукати варіанти оптимізації PHP-додатки.
Чекайте продовження!
Як взагалі в подібних умовах живуть інші проекти?Чи має тоді сенс тримати запущеними кілька nginx ?
Стало цікаво, а що буде, якщо поставити число запущених php-процесів більше, ніж число ядер ?