- PVSM.RU - https://www.pvsm.ru -
Существует мнение, что nginx — отличный инструмент для отдачи статики.
Есть статьи, где описываются настройки sendfile или aio [1] для «улучшения» отдачи.
На Хабре есть чего почитать о настройке proxy_store с proxy_cache для минимизации проблем со стороны мозгов сайта.
Еще в QA иногда возникают вопросы про кеширование картинок [2], например.
Зачем заниматься этой ерундой! — говорят опытные пользователи — OS лучше вас знает как кешировать файлы! С кешем и префетчем в современных OS, точнее FS, проблем нет! Зачем плодить свои кеши и списки популярных материалов и все такое?...
Есть только одно вредное «но» — в среде исполнения nginx (в общем случае Linux) понятие "файл" и вообще «файловая система» — просто понятие.
И однажды, когда я, подмонтировав сервер по sshfs, обновил один скриптик, случилось волшебное:
1. На каждой страничке стало на 4 картинки больше.
2. Сервера сдохли.
Что поделать — картинки хранились на glusterFS. Наступил полный FUSE.
GlusterFS, как и интерфейс FUSE, сильно сжирает производительность, но он того стоит.
Изначально у нас был один сервер. Потом два, второй из который монтировал www с первого по nfs. Потом три, четыре.
Не очень надежно, но так уж исторически сложилось. Для спасения ситуации нужна была некая совершенно прозрачная система, in-place замена nfs. Кластерная ФС.
Сейчас на всех серверах стоит raid 10, и за полтора года эксплуатации он пару раз падал. В том числе совсем. Gluster молча поднимал копию ФС на новой железяке и все продолжало работать. Гластер свою работу знает.
Причина была другая, но решения проблем будет совпадать.
Нет ничего страшнее чем то что "исторически сложилось".
И в одном моем проекте «исторически сложилась» ситуация, когда картинки отдает php.
В свое время нужно было сделать файловый загрузчик с различными ACL, ресайзами и вотермарками. Это было почти 10 лет назад. Механизм прижился и с тех пор не менялся.
Сейчас для решения таких проблем есть много специализированных решений(elliptics [3], backpack [4] и другие; а еще лучше CDN). Но тратить человекомесяцы на переход не хочется. Спать хочется, а не работать.
Да и php чтука, в принципе, неплохая. Но имеет свои пределы.
Хабр, в очередной раз подсказал вариант решения — proxy_store и proxy_cache.
Но proxy_store использовать мне нельзя — сохранить негде, и с proxy_cache тоже проблемы.
Есть одно, большое такое, «но» — много лет назад я уже столкнулся с производительностью отдачи файлов и решил «пускай лучше nginx отдает конечные файлы за меня».
X-Accel-Redirect.
Проблема — nginx не может закешировать ответ из прокси если это не ответ, а команда. X-Accel-Redirect — не кешируется.
Выхода нет?
Теперь вернемся к началу топика.
Нам нужно отдать статику, на этот раз без вмешательства «умных» бэкэндов. Просто статику, но с glusterfs.
Директив для кеширования статики просто нет — не предусмотрены. Считается что OS сама не дура. Для статики есть только open_file_cache и настройка самой передачи файлов(sendfile/aio и компания).
Что делать?
Усложним задачу, и попробуем решить проблему исключительно средствами nginx, не внося никаких изменений в другие коды.
# Static files location
location ~* ^.+.(jpg|jpeg|gif|png|ico|css|js|swf|txt|ico)$ {
root /var/www/kashey;
}
Nginx делает proxy_pass сам на себя, кешируя результат. Возможно тут можно использовать fcgi, но так — нагляднее.
# Static files location
location ~* ^.+.(jpg|jpeg|gif|png|ico|css|js|swf|txt|ico)$ {
set $dopass 1;
proxy_set_header Host $host;
#если у нас есть "кука" - отдаем файл с реальной ФС
if ($http_fiberpass) {
root /var/www/kashey;
#или proxy_pass на бэкэнд
set $dopass 0;
break; #но этот break не работает
}
#настройки кеширования, не забудьте описать proxy_cache_valid
proxy_cache static_cache;
#добавляем прокси "куку"
proxy_set_header fiberpass "nginx";
if ($dopass) {
#отправляем запрос к самому себе.
proxy_pass http://127.0.0.1:80;
}
}
И никакой магии.
В случае с X-Accel-Redirect схема такая:
1. nginx получается запрос
2. пересылает себе, к сожалению запрос полный и реальный.
3. пересылает на прокси
4. получает ответ и отдает файл
5. ответ кешируется
6. ???
7. PROFIT
В случае с обычной статикой сложнее — root не заканчивает выполнение, break и return также не работают. Настройка прокси не может находиться внутри условного блока.
В смысле с X-Accel-Redirect с apache снимается вал запросов. На загруженной системе разница может составить 50 раз.
Но это понятно — php сам по себе, а через апач тем более, не самое реактивное решение.
Latenсy запроса меньше 40мс, лично у меня, не получался (общее время php+gluster).
В случае использования варианта с proxy_cache скорость отдачи приравнивается к скорости отдачи статики.
Отдача с gluster — 13мс — это нормальное время для системы без кеша.
Отдача из кеша — 1мс — это замечательное.

Важно учесть — сервера находятся в Германии, а клиенты в России.
Нормальные пинги до сайта 60-100мс.
Так что для клиента ускорение практически не заметно.
Но оно заметно для сервера.
1. Снизилась нагрузка на сервера, в том числе в попугаях Load average и soft-irq.
2. Снизился трафик между серверами (можно решить включив WORM(Write Once Read Many volume), но это уже не «прозрачно»).

3. Все стало работать чуть быстрее.
В итоге работы которые на 10% снизили скорость реакции на клиенте, получились в результате 10-ти кратного ускорения отдачи статики. Что снизило общую нагрузку на сервера примерно раз в 20.
Обратное утверждение, к сожалению, тоже будет верно — сколько не старайся, клиент может и не заметить.
PS: Многие знакомые сисадмины даже не допускали мысли о возможности работы такой схемы. Не позволяет кешировать/проксировать — значит нельзя.
Хорошие программисты не всегда хорошие сисадмины, а сисадмины, обычно, вообще не программисты.
Настоящие герои всегда идут в обход, в брод, и на велосипедах.
PPS: я, кстати, не сисадмин. И, быть может, все сделал не правильно.
Автор: kashey
Источник [5]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/nginx/48428
Ссылки в тексте:
[1] aio: http://habrahabr.ru/post/68480/
[2] кеширование картинок: http://habrahabr.ru/qa/32141/
[3] elliptics: http://habrahabr.ru/company/yandex/blog/200080/
[4] backpack: http://habrahabr.ru/post/184652/
[5] Источник: http://habrahabr.ru/post/202290/
Нажмите здесь для печати.