Pull to refresh

Comments 79

Бред какой-то. У вас что-то с диском, раз nginx выдает 1 респонс в секунду на статику. И что от тюнинга сети вдруг все залетало. На моей VPS, которая, к слову, сильно дешевле вашей, обрабатываются 100+ php-запросов без проседаний.
Хм, касательно статики прошу посмотреть сей лог, минуту назад как из консоли:
ab -n 10000 -c 1000 http://*.org/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking *.org (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests


Server Software:        nginx
Server Hostname:        *.org
Server Port:            80

Document Path:          /
Document Length:        22307 bytes

Concurrency Level:      1000
Time taken for tests:   4.959 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      228906082 bytes
HTML transferred:       226318546 bytes
Requests per second:    2016.42 [#/sec] (mean)
Time per request:       495.928 [ms] (mean)
Time per request:       0.496 [ms] (mean, across all concurrent requests)
Transfer rate:          45075.28 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  175 220.2    126    1195
Processing:    13  296  98.9    323     498
Waiting:        2  141  77.2    122     347
Total:        149  471 252.1    457    1564

Percentage of the requests served within a certain time (ms)
  50%    457
  66%    482
  75%    492
  80%    514
  90%    616
  95%    709
  98%   1458
  99%   1554
 100%   1564 (longest request)



Относительно Вашего VPS и его настройки, не могли бы Вы поделиться своими наработками, ибо 100+ php-запросов без проседаний, на мой взгляд, отличный результат. Если у вас WordPress и на дешевом VPS — Вы отлично поработали и мне хотелось бы научиться у Вас такому мастерству. И если Вас не затруднит, было бы интересно увидеть, что за VPS и почем.
У меня не wordpress, а проект на codeigniter. И, вроде, ничего особо не настраивал для производительности. У вас с нодой что-то конкретно не так, что nginx выдает так мало статики.
Спасибо за ответ, он заставил меня задуматься о дальнейших исследованиях настроек nginx. Дело в том, что я не смог найти VPS дешевле $10 в месяц (со вторым IP получается $12 в месяц) и считал, что это нормальное поведение для него. Вы меня озадачили тем, что нужно как-то выяснить, как ведет себя эта XEN-нода (я правильно назвал?), только вот я не знаю как. Гугл-обучение мне в помощь, но это будет позже. Конечно, после выяснения всех нюансов я дополню статью свежими изысканиями. Вы не могли бы подсказать, где можно посмотреть предложения по VPS дешевле моего?
Премного благодарен за ссылочки. Это оказывается называется low-end, что вполне логично. Буду присматривать, поскольку как раз собирался брать отдельный VPS для одного из своих городских проектов.
Относительно codeigniter не сталкивался, но слышал. Но, уверен, у WordPress во много раз большие аппетиты. Например, установленные на этом же VPS DataLife Engine и OpenCart (с sample-content) выдают примерно 30-50 r.p.s. в моих пробах с siege. Но и это, я уверен, весьма жалкий показатель, и он сейчас таков потому, что php весьма «тучен» (вкомпилена куча модулей в него и я не могу понять, как их грамотно отключить, так что бы ничего не поломать, надо ещё читать и читать). По результатам перекомпиляции PHP в будущем обязательно сделаю апдейт статьи.
Аппетиты вордпресса сильно зависят от разработчика. Скажем достался мне один проект как-то на «пофиксить» — там вывод каждой строки вызывал запрос к базе. В среднем страница генерилась 2 секунды. Потратив пару часов + установив плагин кэша прожорство уменьшилось в 4 раза, и уверен там можно было еще что-то сделать.

Но я все же предпочитаю проекты на фреймворках (CI, Yii, Symfony2) с которыми и работать приятнее, и с производительностью проблем нету (если и есть то это исключительно вина разработчика).
WP же использовал раньше только для простеньких сайтов визиток только из-за удобной админки. Но если логика сайта посложнее сайта визитки или там добавляются какие-то плюшки, дешевле и быстрее написать узкоспециализированную CMS под эти задачи на базе популярного фреймворка.
Благодарю за рекомендации. Я начинаю присматриваться к Yii. И я согласен с Вами относительно WordPress'а. Однако я никогда не думал, что сайты о небольшом курортном городке будут популярны так, как сейчас, поэтому и делал на WordPress.

На мой взгляд, сейчас имеет смысл на примере WP провести полную оптимизацию системы в целом, что бы было достаточно «граблей и шишек» в этом отношении (я не нанимаю администратора с его кучей «шишек», всё своими силами). А после тюнинга можно будет вплотную занятся проектами, тем более, как оказалось, народ интересуется.
Давненько читал её в оригинале. Единственное, что в ней понравилось — это вариант отдачи кешированных гзиппованных страниц. Обработке зарегистрированных пользователей там совершенно не уделено внимания. До Варниша пока не добрался — поковыряю его, как время будет. Спасибо за ссылку на русский перевод.
Насколько я понял, /dev/shm/ — это shared memory (конечно я могу ошибаться). Но судя по операциям — гораздо шустрей диска.
В таком случае, судя по документации, нужно писать apc.mmap_file_mask=/apc.shm.XXXXXX
Да, вы конечно правы. Перепроверил документацию, исправляю на VPS и в статье.
Проверяйте скорее скорость файловой системы:
dd if=/dev/zero of=olo_test bs=64k count=16k conv=fdatasync

Что-то не так в вашем десятидолларовом королевстве :(
Благодарю за помощь. Вот результат.
# dd if=/dev/zero of=olo_test bs=64k count=16k conv=fdatasync
16384+0 записей считано
16384+0 записей написано
1073741824 bytes (1,1 GB) copied, 9,16004 секунд, 117 MB/s

Как Вы его оцените? Я, например, довольно слабо себе представляю, что такое 117 MB/s в понятиях «очень медленно» | «медленно» | «нормально» | «быстро» | «очень быстро». Перед запуском команды я бегло просмотрел man. Насколько я понял, последняя цифра и есть приговор. Теперь оценить бы его.

Хотя (включаю мозг), гиг за 9 секунд, вроде вполне себе прилично.

P.S. «десятидолларовом королевстве» — классная фраза, очень понравилась :)
Да, нет — со скоростью файловой системой всё нормально.
где-то между «нормально» и «быстро».
Можете прогнать тесты с serverbear.com/add-benchmark (предупреждаю, это займёт время — в моём случае заняло чуть меньше часа). Там же можно удобно выбрать сервер по параметрам (стоимость, память, расположение и т.д.).
Благодарю за рекомендацию. Конечно, в данном случае хотелось бы собственных шишек. Ресурс Вами предложенный изучу безотлагательно.
Интересно вы apc вы размещаете в памяти и выдаете ему 120Мб если у вас всего в системе 256 Mb RAM.
С ума можно сойти с такими ресурсами выжимать все, гораздо проще взять у тех же фаствпс тариф с 1200 Mb 1700 Mhz за те же деньги, чем заставлять систему постоянно драться за ресурсы.
Вы, видимо, очень избалованы оперативкой. Нормально написанные CMS без труда работают на VPS с 128мб оперативкой, и еще и остается.
Сферические VPS в вакууме =) А если база уже 2Гб?)
Я сторонник того, что быстрее деньги заработать на более дорогой тариф, чем тратить значительно большее время на ужимки и пользователей мучить долгой отдачей страниц и нестабильным поведением сайта в пики.
Тоже так развлекался с зажатыми ресурсами и оптимизацией под них, но это интереса ради, если сайт уже бизнес, то это выходит себе дороже.
А если база уже 2ГБ, то и не нужно покупать VPS за $10.
Сферические базы в 2GB :) Что вы туда положили, картинки?!
Смотрю на одном из своих сайтов база почти в 1 млн. записей, занимает меньше 200MB…
Нет, флудеры, комменты + личка = 1.1Гб в базе.
До бизнеса моим сайтам ещё очень далеко (с Директа капает $15 в месяц). А клиентский мизер может свободно уехать на какой-нибудь шаред-хостинг и жить на кешах, или вообще на статике. Его все равно никто годами не обновляет.


Может я не прав, но мне кажется драка за ресурсы не такая уж активная, а как Вы считаете?

После установки PHP из сорцов значительно вырос показатель. Наверняка надо пересобирать PHP с вырезанием ненужных библиотек. Но я не знаю, как это сделать так, что бы все работало корректно.
Мне интересно больше на сколько система в swap уходит.
Подавляющее количество времени это выглядит так:





Я уверен, что это из-за объема бинарника PHP.
Все не так и плохо, интересно если вообще с swap уходить не будет на сколько быстрее будет.
В текущей ситуации — в свап будет валиться в любом случае. На данный момент отдача практически постоянно кешированная. Я уверен, вся проблема в php, который надо перекомпилить с вырезанием ненужных модулей.

Сейчас это выглядит так:
1355347892-clip-4kb
Сколько усилий, лишь бы не 512 мегов оперативы :)
К сожалению, моё хобби пока само себе не заработало на 512 мегов. Но я думаю, в скором времени этот рубеж в Директе будет пройден. В любом случае, опыт оптимизации будет полезен при любой конфигурации, Вы так не считаете?
Есть куча VPS-ок где за те же 10 баксов >512 оперативки.
А как с вопросом стабильности, надежности и постоянства? У Inferno на searchengines хорошие отзывы.
Пока не жалуюсь. Для серьезных проектов не подходит конечно, но оно и понятно. Серьезные проекты не хостятся на VPS-ке за 10 баксов. А так для странички/бложика/сайта визитки вполне подходит.
Мое мнение может покажется несколько странным, но пока проект не обрел бизнес-модель — это хобби. А Вы на каких VPS-ках бложики держите? Ссылка была в тему :)
Отличное предложение! Спасибо! Присматриваюсь!
Вечером, после установки worker_aio_requests 128; в контексте events конфига nginx — вся статика стала откликаться гораздо быстрее. Даже очень.

Господа и дамы специалисты, подскажите пожалуйста, как правильно скомпилировать минимализированный PHP? Он у меня слишком большой из-за кучи вкомпиленых модулей. Кушает ресурсов очень и очень много и в этом сейчас я вижу главный затык.
Кстати, в документации написано:
Для работы AIO нужно выключить sendfile

на ваше счастье там есть еще строка
Явно выключать sendfile не нужно, так как при использовании directio он выключается автоматически.
А какой смысл использовать AIO при отдаче статики? Насколько я помню профит от AIO реально можно получить только при отдаче больших файлов, хотя бы в несколько мегабайт.
В документации пример как раз для папки с видео был =)
Ооо, благодарю Вас за указание на мою невнимательность.

Только что попробовал: при общих равных (с учетом ручного open_file_cache prime) aio проигрывает sendfile в моём случае 400 rps. ~2000 против ~2400. При этом Time per request примерно на 15% ниже (лучше) у sendfile. Отключаем aio, оставляем sendfile.

И это во много раз больше того показателя (60 r.p.s.), который я озвучил в статье, как первую «победу». Сейчас я понимаю, что 60 — это просто смешно.
AIO с таким конфигом у вас просто не работает. Опять же отсылаю вас к документации: nginx.org/r/aio/ru
А как определить, что работает — aio или sendfile?
По размеру запрашиваемого файла. Если вы выставили directio 5m;, то файлы меньшего размера будут отдаваться без использования directio и соотвественно aio в linux.

Поскольку у вас получилось аж 2000 запросов в секунду (2000 * 5 Мб = 10 000 Мб/сек), то я сделал вывод, что тестировали вы на файлах гораздо меньшего размера.
Кстати, в документации написано:
Для работы AIO нужно выключить sendfile

Эта строчка относится к AIO на FreeBSD.
А без APC и без других акселераторов тут вообще никак?
Уверен на 70%, что причина в нём.
Где-то читал тесты всех акселераторов для PHP, где был сделан вывод, что все они так или иначе вешают процессы PHP/apache через какое-то время (в Apache это совершенно не поддажющиеся анализу периодичный Segmentation fault). На низких нагрузках не заметно. На 100к хитах уже очень напрягает (апач приходилось рестартовать скриптом раз в 2 часа).

Еще момент:
Мало кто пишет и знает, что eAccelerator в mod_php Apache сильно увеличивает размер каждого процесса php. Дело в том, что в таком случае память eaccelerator.shm_size не общая shared (как везде пишут), а для каждого чайлда отдельная. Вроде как, для php-fpm кушается память для каждого воркера (точно чтиал про такое в xcache).

В общем, просто попробуйте отключить APC и посомтрите что будет.
Не знаю как в APC, но советую последить за размером процессов.
На моих проектах APC значительно снижает время работы скрипта + уменьшает потребеление памяти на запрос. Так что думаю увеличение потребления памяти воркерами это не такая уж и большая проблема.
Без акселераторов точно никак. APC однозначно ускоряет работу PHP во много раз. Для примера, генерация главной страницы сайта на домене .TV без акселератора происходит от 19 до 26 секунд (это чуть более 400 запросов в базу, при этом ни один не является медленным). С акселератором (opcode cache) первая генерация (prime opcode cache) — 3-8 секунд, последующие — 0.5-0.8 секунд. Т.е. прирост скорости более 3000%, что является значительным.

Да и Facebook наглядно показывает, как работает APC.
мне кажется что 400 запросов на страницу это даже для супер-пупер соц-сети на WP многовасто как-то. Быть может неправильная архитектура и не хватает кеширования?
Вы абсолютно правы относительно количества запросов. Это недопустимо много, и причина кроется в весьма «кривой» используемой теме. Для себя я уже поставил во втором приоритете сделать новую тему «руками». Кроме того, после прохождения мной определенного тренинга я сейчас понимаю, что визуальная подача информации на .TV совершенно не соответствует самой информации, предлагаемой сайтом.
хм, по опыту — оптимизируйте WP, плагины там, тему. Минимальными телодвижениями можно улучшить в разы. По дефолту идет куча обращений в базу, которые легко удаляются, плагины надо пересмотреть — у WP нет никаких политик вокруг плагинов и тем и в результате они написаны ужасно, в основном.
Потом уже под оптимизированный WP надо тюнить систему.

Не берусь судить, но раньше на мелкие VPS ставили FreeBSD, потому как сама операционка была менее требовательная и тюнилась лучше.
Полностью согласен про WP. Для крупных проектов думаю отказаться от него, а вот для мелких — его следует полностью оптимизировать. Однако вопрос про перекомпиляцию PHP все ещё в силе.
Прирост от собственной сборки PHP по сравнению с установкой из пакетов есть? Я как-то пробовал на своей локальной машине экспериментировать. Собрал себе nginx свой и свой php. Прирост производительности конечно был но не большой.
С учетом того, что я не умею правильно собирать PHP (1 раз смог собрать, так что бы сайты работали; все модули вкомпилены внутрь) — прироста не просто нет, есть явное и заметное снижение производительности PHP. И это приоритет номер один — правильно собрать PHP, без лишних модулей.

Но проблема стоит в том, что я не знаю, какие модули правильно будет вкомпилить в PHP, а какие сделать загружаемыми (.so). Мало того, я даже не представляю, какие модули являются реально необходимыми для WP. Именно поэтому я и прошу сообщество Хабра помочь мне в этой нелегкой для меня задаче.
Насколько я помню всякие штуки как префетчи сильно упрощают жизнь при загрузке библиотек (этим операционная система должна заниматься). Более того, воркеры PHP-FPM уже загрузили нужные библиотеки или нет? Я к сожалению этого не проверял.
Что такое «префетчи»?

Не совсем понял фразу «воркеры PHP-FPM уже загрузили нужные библиотеки или нет?»
Во всех нормальных осях реализована предзагрузка в оперативную память наиболее используемых библиотек. Ну мол что бы снизить время запуска. Если честно мало чего могу сказать по этому поводу.

А что касается PHP-FPM… ну как бы фишка FPM что воркеры все время висят в памяти и ждут запросы на обработку. Логично предположить что библиотеки необходимые они загрузили в память сразу же. А расходы на вызовы методов библиотечных настолько несущественны что их можно не учитывать.
Спасибо за подробный ответ относительно FPM.

Вы не знаете, какие PHP-модули реально нужны исходя из следующего:
# php -m
[PHP Modules]
apc
bcmath
calendar
Core
ctype
curl
date
dom
ereg
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
intl
json
libxml
mbstring
mcrypt
memcache
mhash
mysql
mysqli
mysqlnd
openssl
pcre
posix
Reflection
session
SimpleXML
sockets
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
xml
zip
zlib

[Zend Modules]


Я без понятия что используется в WP. Думаю там не используются рефлексии, думаю что SPL там не используется, но может использоваться в плагинах, ровно как и рефлексии. Один из драйверов mysql точно не используется, какой именно, это уже надо настройки смотреть. Думаю что не используется DOM и SimpleXML (опять же если только плагины используют). Словом если вам так критично потребление памяти, то для того библиотеки эти и выносятся в so файлы, что бы на все процессы в память библиотека загружалась один раз. Тут нужно выбирать что вам нужно, производительность (не думаю что она уж так сильно растет, думаю вам пару милисикунд погоды не сыграют. Намного профитнее тогда уже сессии хранить в памяти, хотя опять же для этого должна быть свободная память.
Ооо, это действительно полезный ответ. Я хотел бы уточнить, правильно ли я Вас понял: если модули вынесены в so — то они загружаются один раз для всех процессов php?
Я конечно могу ошибаться, но вроде как в этом суть Shared Objects (.so) так же как и Dll
Исходя из Ваших слов я перекомпилировал PHP, по максимуму вынес все модули в so. В общем, стало чуть чуть быстрее, но не намного. Следующий и самый важный этап — это оптимизация Wordpress.
Опыт оптимизации окружения

Где-то тут пропущено слово "неудачный".

Конфиг nginx просто ужасен. Я промолчу про кучу кривых if-ов и регулярок, но вот чем объяснить, например, это: fastcgi_connect_timeout 1800s; — представить даже трудно.
Наверняка Вы правы. Я был бы Вам признателен, если бы Вы написали, каким образом нужно изменить настройки.

1800s — это вполне актуальный параметр при загрузке пользователем пары сотен мегабайт фотографий. Меньшее значение не давало такой возможности. Я Был бы Вам признателен за помощь в работе над ошибками, это будет весьма полезно.
Сначала стоит оптимизировать код, снизить нагрузку на базу, уменьшить время генерации страницы, добавить кэшер какой-нибудь ну и т.д., а потом уже заниматься более детальной оптимизацией (параметры PHP-FPM, настройки nginx, настройки MySQL… есть много вещей сильно влюящих на производительность и не требующих таких лютых извращений).
На данный момент, за счет нескольких уровней кеширования нагрузка на базу значительно упала. В любом случае, там где раньше было около 400 запросов — сейчас выполняется 9-17 запросов, причем довольно быстро. Запросы/результаты/части запросов и результатов кешируются на уровне БД и в APC user cache.
1. Настройки большинства директив по-умолчанию имеют вполне разумные значения, взятые отнюдь не с потолка, и изменяя их без четкого понимания что вы делаете, и для чего меняете, какую проблему решаете — будет только хуже.
2. Есть же документация, в чем дело? Причем на родном языке: nginx.org/r/fastcgi_connect_timeout/ru Почему никто даже не смотрит в документацию, зато каждый пишет свой «туториал» едва только впервые настроил свой домашний сервер? Она же для вас и пишется. [...] Даже значение по-умолчанию в 60s достаточно велико: в обычных условиях connect() (man connect) выполняется менее чем за единицы миллисекунд. Установив значение в 60 минут вы просто лишили nginx и себя возможности узнать о проблемах с бэкендом. Ни один клиент не будет ждать 60 минут пока сервер сообразит, что «тут уже делать нечего» и вернет 502. В итоге со стороны клиента это будет выглядеть как зависший сервер, а с вашей стороны как клиент оборвавший соединение (ушел на другой сайт или закрыл браузер). То же касается других таймаутов, что вы наоптимизировали. Взять вот fastcgi_read_timeout. Что написано? Процитирую:
Таймаут устанавливается не на всю передачу ответа, а только между двумя операциями чтения.
и это там не сейчас появилось.
Благодарю за ответ. Я прочитал документацию и несколько раз пробовал менять настройки. Однако, для загрузок файлов не помогало ничего, кроме увеличения соответствующих тайм-аутов.

Но ради интереса я, следуя Вашим словам, закомментировал все fastcgi timeout директивы. В итоге при попытке загрузки пары десятков фотографий всего лишь по 3 Мб я, как и раньше, получаю 502 ошибку строго через 60 секунд. При этом, естественно, фотографии не загрузились и соответствующий скрипт не смог их обработать. У Вас наверняка есть идеи, какие ещё нужно подкрутить настройки, кроме fastcgi тайм-аутов, дабы фотографии загружались и могли быть обработаны с помощью php-fpm?
Очевидно крутить нужно не nginx, а ваше приложение, в которое всё упирается. И 502 ошибка спустя минуту ясно говорит о том, что у вас с обработкой таких запросов большая проблема.

1. Обабатывать фотографии необходимо отдельным потоком, чтобы не ухудшать взаимодействие с сайтом остальных пользователей, которые просто зашли и ничего не загружают.

2. Вы в любом случае не можете обработать за единицу времени более фотографий, чем позволяют ваши ресурсы. И заставлять пользователя ждать, пока эти ресурсы найдуться — очень плохая идея. Вам нужно вынести саму обработку в фон. Пусть nginx принимает файл, сообщает об этом бэкенду, а тот ставит задачу в очередь и сразу после этого возвращает 200-ый ответ пользователю, который говорит о том, что файл успешно загружен. А некий отдельный процесс, работающий независимо слушает очередь заданий, и по мере того, как он заканчивает обработку одной фотографии, переходит к следующему заданию. В итоге, и фотографии будут обработаны быстрее, и пользователь может продолжать пользоваться сайтом, или загружать ещё фотографии, не дожидаясь пока они будут обработаны, и сервер будет при этом устойчив к подобного рода нагрузкам.
Я как раз думал над возможностью такой реализации. Что Вы думаете о nginx upload и nginx upload progress?
Оба модуля не имеют к этой задаче никакого отношения. Nginx upload — очень специфический модуль, плохо себе представляю, в каких случаях он требуется. Upload progress — это такой устаревший способ для отображения прогресса загрузки, утратил актуальность с появлением поддержки XMLHTTPRequest2 в большинстве браузеров.
Насколько я понял, Nginx upload может загрузить файлы и только после окончания загрузки обратиться к бэк-энду для дальнейшей обработки. Подробной документации я почему-то не нашел — только примеры реализации. Скажите, насколько я ошибаюсь?
Насколько я понял, Nginx upload может загрузить файлы и только после окончания загрузки обратиться к бэк-энду для дальнейшей обработки.
Это nginx делает всегда и без этого модуля.
Хм, если это так — значит есть некая проблема при загрузке, которую я пока не могу диагностировать. Спасибо огромное за детальные и очень полезные ответы.
Интересно узнать, как обстоят дела. Какой опыт появился за это время?
Sign up to leave a comment.

Articles