Старая школа велит нам генерировать все необходимые миниатюрки сразу после загрузки базового изображения. Способ проверенный и надёжный, однако, мы живём в изменчивом новом мире, в котором нам может понадобится новый размер миниатюрок с утра в понедельник. Поэтому генерировать миниатюрки будем на лету, по запросу.
Для дела нам понадобится ngx_http_image_filter_module, модуль, который умеет трансформировать изображения в форматах JPEG, GIF и PNG. Модуль стандартный, но по-умолчанию не собирается, поэтому перед сборкой нгинкса нужно добавить его:
./configure --with-http_image_filter_module
Теперь ставим libgd способом, принятым у нас в системе, и собираем нгинкс. Кстати, при сборке из портов FreeBSD достаточно выполнить make config и выбрать нужный модуль в списке.Просто пережимка
Для простоты будем считать, что у нас есть домен images.domain.ru, с которого выдаются картинки лежащие в /path/to/images. Запросы к/some/image.jpg будут выдаваться напрямую, к /120x90/some/image.jpg или /120x-/some/image.jpg будут жаться в миниатюрки (во втором случае идёт масштабирование только по ширине). В таком случае получаем:server {
server_name images.domain.ru;
root /path/to/images;
if ($uri ~ ^/(\d+|-)x(\d+|-)/) {
set $w $1;
set $h $2;
}
location / {
}
location ~ ^/(?:\d+|-)x(?:\d+|-)/.*\.(?:jpg|gif|png)$ {
rewrite ^/[\w\d-]+/(.*)$ /$1;
image_filter resize $w $h;
break;
}
}
Что тут происходит? Сначала мы определяем размеры миниатюрки и устанавливаем соответствующие переменные. Затем выдаём статику и переходим к выдаче миниатюрок, рассмотрим второй location по-подробнее:
rewrite перенаправляет url на настоящий файл, image_filter уменьшает полученную картинку, break предотвращает внутренний редирект с выходом из location. Последнее важно иначе нгинкс пройдёт весь путь ещё раз с уже переписанным URL и выдаст полную картинку.Можно добавить предопределённые размеры:
if ($uri ~ ^/small/) {
set $w 120;
set $h 90;
}
location ~ ^/(?:\d+|-)x(?:\d+|-)|small/.*\.(?:jpg|gif|png)$ {
...
Этим можно уже пользоваться если не жалко процессора, к слову на FreeBSD 8/Core 2 Quad Q9550 @ 2.83GHz/DDR2-800 удавалось пережимать 200 картинок в секунду (jpeg, 640x480 -> 150x150). Но, конечно, нам процессор жалко, поэтому будем пережатые картинки кэшировать.
Пережимка с кэшированием
Кэшированием в нгинксе занимается ngx_http_proxy_module, кэширует он только то, что проксирует, поэтому нам понадобиться извернутся — будем слушать два порта и проксировать сами себя:proxy_cache_path /path/to/cache levels=1:2 keys_zone=thumbs:10m inactive=24h max_size=5G;
server {
server_name images.domain.ru;
location ~ ^/(?:\d+|-)x(?:\d+|-)|small/ {
proxy_pass http://localhost:8081;
proxy_cache thumbs;
proxy_cache_valid 200 24h;
proxy_cache_valid 404 415 1m;
}
location / {
root /path/to/images;
}
}
server {
listen 8081;
... конфигурация пережималки ...
}
Готово, теперь на вышеупомянутой системе нгинкс выдаёт 15000 картинок в секунду, если всё из кэша, — чертовски быстро. Я не буду расписывать настройки, они неплохо расписаны в документации модуля. А полный конфиг можно взять тут.