Кэширование динамических изображений

Avenus

Under Glory Yield
Кэширование динамических изображений

Привет, всем! :)

Прочитал много информации по этой теме.
Пробовал разные варианты.

Исходные данные:
Генерируется изображение с применением библиотеки GD2
(изменение размеров, водяной знак...)

Сервер отдает заголовки (указываю):
PHP:
header('Content-Type: image/jpeg');
header('Content-Transfer-Encoding: binary');
header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
// Даже дату в будущем указываю
$dt_tmp=getdate(date('U'));
header('Expires: '.gmdate('D, d M Y H:i:s',date('U')-(86400*($dt_tmp['wday']-8))).' GMT');
header('Cache-Control: public, must-revalidate');
header('Pragma: public');
Проблема:
Тестирую через FireBug: для этих изображений ну никак не хочет включаться кэширование.
Постоянно генерируется изображение и возвращается статус 200 OK.

Что я не так делаю или где можно все-таки узнать что нужно сделать и как правильно?

Спасибо всем, кто отзовется ;)

-~{}~ 15.01.10 02:04:

Использую фреймворк CodeIgniter.
Пока сделал такое кэширование:
- Идет запрос на изображение
- Проверяется наличие его в кэше:
-- Если есть, то оно автоматически отдается сервером
-- Если нет, то генерируется и записывается в папку для кэша

Думаю, что способ неудачный, т.к. получается нерациональное использование дискового пространства, хоть и выигрыш в нагрузке на сервер.
 

Avenus

Under Glory Yield
При копипасте сюда забыл вырезать, извиняюсь.
Я убрал постоянную обновленную дату модификации, но это не помогает.

-~{}~ 15.01.10 02:56:

Про будущее, вообще-то: Expires
 

dimagolov

Новичок
Avenus, ты понимаешь вообще, что заголовки это для кеширования на клиенте и никакого отношению к генерации и хранению картинки на сервере не имеет?
похоже, что ты хочешь отдавать 304-й код, то есть сообщить клиенту, что картинка не изменилась и не отдавать ее вообще (а не только не перегенегировать ее и брать с диска), но подобный код сервер можно отдать только получив соответствующую информацию от клиента
 

Avenus

Under Glory Yield
dimagolov, да. Я понимаю, что для кэширования на клиенте. Поэтому и пытаюсь сделать так, чтобы браузер брал сгенерированное и загруженное изображение из своего кэша, а не обращался каждый раз за ним на сервер.

-~{}~ 15.01.10 05:19:

При генерации изображения обязательно нужно указать тип:
PHP:
header('Content-Type: image/jpeg');
Также указан вывод в браузер:
PHP:
imagejpeg($resource);
Всё. Больше никаких заголовков нет, убрал.
И ничего не изменилось, как загружал с сервера браузер, так и загружает :)
IE, Chrome, Firefox (в нем и тестирую)

-~{}~ 15.01.10 05:23:

Может есть документация по этому поводу?
Чтобы разобраться ;)
 

Активист

Активист
Команда форума
Конкретно к твоему вопросу - проанализируй заголовки запроса/ответа и подумай, как работает КЕШ:

Код:
Заголовки запроса
Host	stroy.local
User-Agent	Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.1) Gecko/20090624 Firefox/3.5 (.NET CLR 3.5.30729)
Accept	image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language	ru,en-us;q=0.7,en;q=0.3
Accept-Encoding	gzip,deflate
Accept-Charset	windows-1251,utf-8;q=0.7,*;q=0.7
Keep-Alive	300
Connection	keep-alive
Referer	http://stroy.local/
Cookie	phpbb3_hsuct_u=1; phpbb3_hsuct_k=; phpbb3_hsuct_sid=3e6704a93c4932f30e6e8d0ce75e2bf1; PHPSESSID=9p73flg0spc6frmj9iqdk81302
If-Modified-Since	Sun, 15 Nov 2009 16:20:13 GMT
If-None-Match	"5b000000046ea6-1708-4786b4482d642"
Cache-Control	max-age=0

Заголовки ответа
HTTP/1.0 304 Not modified 
Date	Fri, 15 Jan 2010 03:48:15 GMT
Server	Apache/2.2.9 (Win32) DAV/2 SVN/1.5.1 PHP/5.2.6
Connection	Keep-Alive
Keep-Alive	timeout=5, max=93
Etag	"5b000000046ea6-1708-4786b4482d642"
-~{}~ 15.01.10 11:47:

И самое важное - картинку не нужно все время отдавать динмически, а сохранять один раз копию картинки на диске и отдавать статический файл, в случае изменения - изменять файл на диске или ссылку на изобаражение в HTML.
 

Avenus

Under Glory Yield
картинку не нужно все время отдавать динмически, а сохранять один раз копию картинки на диск
Так я и сделал так сейчас :)
Оригинал в закрытом доступе, а копия в открытом - с другими размерами под дизайн сайта, с водяным знаком и т.д...

-~{}~ 15.01.10 06:59:

Я ради чего тему создал. Чтобы узнать, может есть способ заставить бразуеры кэшировать динамические изображения, чтобы 2 файла на хранить на одно изображение... а то и больше:
- оригинал
- мини-превью
- необходимая под размеры версия
 

Активист

Активист
Команда форума
Avenus
Извини, конечно, но включи МОЗГ, ти программист или вор?

Из предыдушего поста:

If-Modified-Since Sun, 15 Nov 2009 16:20:13 GMT
If-None-Match "5b000000046ea6-1708-4786b4482d642"

...
HTTP/1.0 304 Not modified
Что такое заголовки - почитай в интернете.

2. чтобы 2 файла на хранить на одно изображение
Тоже мозг пора включать. Что важнее? 50 кб пространства или 100% зарузка CPU на ресайз 10 мб фото? Ресурсы ЦП ограничены, и процесс ресайза требует много процессорного времени. Твой сайт можно будет положить путем однорвременой отправки 100-200 запросов на просмтотор изображений размером 20-30 МБ.
 

Активист

Активист
Команда форума
Avenus
Ну мысли, идеи в виде кода, нужно не "воровать", а "придумывать".

Хотя, наверное, лучше сказать "кодер" :)
 

Splurov

Новичок
Avenus
Сейчас у тебя клиент каждый раз проверяет изменилась-ли картинка, о чем ты его сам попросил (header('Cache-Control: public, must-revalidate');), т.к. твой код не проверяет заголовки if-modified-since/if-none-match, а просто отдаёт картинку, ты каждый раз получаешь клиентом 200 Ok.
 

Avenus

Under Glory Yield
Что важнее? 50 кб пространства или 100% зарузка CPU на ресайз 10 мб фото?
Что это за пример такой? :)

Реальные цифры:
Оригинальный файл - 300 кб.
Если, чтобы показывать на сайте сохранять 4 копии:
- оригнальный размер с водяным знаком 310 кб
- одного размера с водяным знаком 160 кб
- другого размера с водяным знаком 80 кб
- мини-превью без водяного знака 15 кб
Итого: 865 кб на один файл

Сейчас изображений на сервере для сайта более 10000 объемом, примерно 30 Гб.
Просматривают ежедневно более 5000 этих динамических изображений в различных вариантах.

Нагрузки никакой, зато нихрена не кэшируется :)

Предсталяю себе, если сделать по 4 копии, то объем увеличится в 2,5 раза или примерно 75 Гб.

В чем будет выигрыш?
В скорости загрузки сайта и всё, т.к. нагрузки не ощущается.
(пиковая 1,1%)
Я понимаю, что если бы сайт посещали не 1000 человек в сутки, а раз в 100 больше, то нагрузка была бы ощутимой.

Вот и задумался о том, почему не кэшируются динамические изображения
Вывод, как уже писал изменил на такой:
PHP:
header('Content-Type: image/jpeg');
imagejpeg($resource);
Пробовал добавлять заголовки:
PHP:
header('Cache-Control: public'); 
header('Pragma: public');
Не помогает :)

-~{}~ 15.01.10 20:55:

Кстати, в самом документе для вывода страницы обязательно:
PHP:
header('Cache-Control: no-cache, must-revalidate');
header('Pragma: no-cache')
Но, я не думаю, что это влияет на вывод изображений.
У них же отдельные заголовки, верно?
 
Сверху