Как стать автором
Обновить

Комментарии 21

В копилку — возможности капчагенерации (если сделать в той же луа key-value кеш для капч, по куке/id капчи). Разумеется, существует ReCaptcha, но она не везде заходит, плюс как фолбек.
Ну и рендеринг всякой фигни, типа «картинок счётчиков посещений/активности» или чего-то такого. Архаично, но народу нравится :)
В статье показан очень плохой пример решения этой задачи. Дело в том, что nginx — это однопоточный сервер, построенный на идеологии асинхронного взаимодействия с сетью. Вызовы же imagemagick блокируют эвентлуп, обработка всех запросов встаёт в очередь, тайминги времен ответов (всех, а не только тех, что касаются обработки изображений) начинают дико шуметь.

Т.к. обработка изображений — это очень cpu-intensive задача, но её стоит выносить в многопоточный обработчик.

Очень даже многопоточный. Поэтому залипнет только тот поток, который будет масштабировать картинку.
Собственно точно так же он залипает пока жмёт gzip-ом или brotli.
Если к этой схеме прикрутить кеширование, то вполне себе рабочий вариант.

Кроме того, нормальным решением будет еще и разнести front/resizer на разные nginx процессы, где front принимает запрос, разбирает его, кеширует ответ, а resizer висит на localhost и только ресайзит картинки.
Вы правы, в статье об этом упомянуто.
Я просто конфиг не открывал :-)
У нас еще и по куке «опознает» ретину, и выдает по запросу 100х100 в реальности 200х200.

Не вводит ли это в заблуждение и что вернет кэш другому клиенту?
Много решений для этого есть, например


background: image-set(
url('https://example.jpg?resize=400x400') 1x,
url('https://example.jpg?resize=800x800') 2x)

ну или media

у нас кеш на ресайзере, для него это разные картинки.
Примерно такая схема:
запрос на фронте
//some.host/images/100x100/000F.jpg
have retina cookie -> rewrite 100x100->200x200
запросы на ресайзере
//resizer/images/100x100/000F.jpg — обычный клиент
//resizer/images/200x200/000F.jpg — retina клиент
Кроме того, нормальным решением будет еще и разнести front/resizer на разные nginx процессы, где front принимает запрос, разбирает его, кеширует ответ, а resizer висит на localhost и только ресайзит картинки.

А какой смысл держать ещё один nginx, который будет заниматься только сжатием картинок? Не вижу преимущества никакого. Тогда уже можно просто сделать FastCGI-шный скрипт, который будет жать картинки и отдавать на front.
Не отдельный, архитектура остается типовой Nginx front + Nginx back. Фронт является балансировщиком, занимается кэшем и т.п. А бэк обслуживает само приложение + еще один upstream куда проксируются запросы ресайза.
У автора он тот же самый, а не другой. Другой всмысле virtual server, но он может быть и на отдельной быстрой, по процессору, тачке. У нас они вообще на хранилках картинок, где процессоры, очевидно, не загружены. И балансер, который и отдает основную статику, сверху.
nginx многопроцессный, но не многопоточный. Точнее, там есть пул потоков, но он используется для IO операций с диском, content_by_lua* исполняется прямо в основном эвентлупе. В качестве проверки можно пострелять в него хотя бы через ab, чтобы ресайзилась большая картинка, и посмотреть top по потокам любого из процессов-воркеров.
Спасибо за уточнение. Я считал что в thread pool вынесено вообще всё блокирующее.
Если разные пользователи через web загружают фотки, которые попадают в папку на сервер, например, image_all.

Подскажите, пожалуйста, как правильно автоматизируют процесс, чтобы, например, в папке image_01 получать эти фотки в конкретном разрешении без потери качества?

Как это делают на порталах продаж и какие трудности, возможно, неочевидные возникают?
Понятно, что есть модерация фоток, а на стадии image_all получают ссылку в базе данных.

Вот в ручном режиме пробовал прогой ImBatch, — понравилось, только ищу автоматизацию.
Тут основная прелесть в том, что вам не нужно нарезать разные размеры предварительно. Это делается на лету параметризованно. Т.е. сохраняете вы при загрузке лишь одно оригинальное изображение и выдаёте любой ресайз динамически по запросу. И можно не хранить его нигде, разве что в кэше.

Объясните пожалуйста почему не используется предварительное создание разных размеров изображений? Неужели вариантов на столько много, что время процессора стоит дешевле места на диске?

В нашем случае много, т.к. это универсальное решение не для одного сайта.
+ время процессора будет затрачено 1 раз в сутки, дальше будет отдаваться из кэша. Да и то, даже первый ресайз происходит очень быстро.
У нас, к примеру, вариантов картинок около 10 штук на каждую. Хранить это совершенно ни к чему.
А что будет если клиент начнет в цикле запрашивать разные экзотические размеры? Как быстро сервер ляжет от нагрузки и/или забъётся кэш?

Смотря чего вам требуется достигнуть.
Можно настроить rate limit чтоб не долбили часто ngx_http_limit_req_module
Можно нормализовать экзотические размеры, типа 365x365 => 400x400
Можно ограничить с помощью ngx_http_secure_link_module
Ну или любую логику на lua добавить.

Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации

Истории