Alter.Org.UA  
 << Back Home EN en   Donate Donate www/www1/www2

Кеширование HTTP

Вводная

В целом, эффективно работающий кеш сокращает время открытия странички. Это уже немного обсуждалось тут, но общая идея в том, что даже при очень широком канале время ответа сервера начинает сказываться. При пинге 30мс скачивание 50 иконок занимает минимум 1.5 секунды. При использовании кеша (Proxy), находящейся локально - практически мгновенно. Прокси провайдера с пингом 1мс - около 50мс, тоже можно считать, что мгновенно. Это раз. Тут кешировать полезно даже на стороне клиента. Т.е. на собственном компьютере. Также, локальная proxy очень поможет на медленном канале (GPRS, DSL). А кроме того, на уровне proxy можно резать нежелательный контент (например, баннеры), что опять таки, особенно актуально в условиях медленного канала. Об этом в описании Local Proxy.

На уровне провайдера кеширование обеспечивает быстрый доступ к условно медленным или перегруженным ресурсам. В отличие от локальной прокси, которой позволительно пропускать через себя весь пользовательский трафик без ущерба для производительности, на уровне ISP нужно как-то выделять ресурсы, кеширование которых целесообразно, а остальное пропускать напрямую. В 1-ю очередь это касается популярных видео- и аудио ресурсов (youtube, rutube, vkontakte и т.п.)

И совершенно отдельный вопрос - что кешировать, а что нет. И как агрегировать различные URI, указывающие на один и тот же ресурс. На днях провел небольшое исследование на тему кеширования youtube video.

HTTPS caching

Замечательный протокол для относительно безопасной передачи данных, не предназначенных для чужих глаз. Относительно - потому что спец-службам, когда очень надо, все равно удается почитать. Радует лишь то, что приходится потрудиться. Но речь не об этом. Реально приватных данных в передаваемом контенте не так много. Пароли, быть может частная переписка, анонимные публикации. Баннеры, код java-script'ов, обслуживающих сайт, элементы дизайна, картинки/видео/музыка, выложенные на всеобщее обозрение вряд ли нуждаются в шифровании. Это и так публичные данные. HTTPS тут может помочь с подтверждением достоверности данных, что никто не изменил их по дороге. С точки зрения кеширования применение HTTPS для всего контента вредно.

  • долгое время по стандарту протокола кеширование данных, переданных по HTTPS даже на стороне клиента запрещалось. Поэтому относительно старые версии браузеров, а также многие новые без специальных настроек ничего не кешируют.
  • без спец. изысков невозможно прозрачное кеширование на стороне ISP, т.к. данные должны расшифровываться уже на стороне клиента
  • кеширование зашифрованного контента сомнительно, т.к. заголовки с информацией о времени жизни объекта недоступны
  • не работает сжатие данных, т.к. делать это можно/нужно до шифрования.

Было бы осмысленно изначально разделить контент на приватный и публичный и использовать https и http сообразно случаю. Также, для контроля доставки данных, можно по https передавать контрольные суммы нешифрованного контента. Некоторая сложность заключается в том, что многие браузеры ругаются на страницы со смешанным контентом. И в том, что отдельная передача контрольных сумм нигде и никак не предусмотрена.

Можно еще поступить так, как сделал Facebook. Авторизация и личный кабинет по HTTPS, лента новостей и т.п. - по HTTP.

Кеширование YouTube online video

Решил разобраться, почему не кешируется видео с YouTube. Казалось бы, должно. Ведь при каждом просмотре содержимое не меняется. Squid настроен так, чтобы кешировать запросы с GET параметрами (типа http://test.net/data.php?id=12345). Тем не менее, этого не происходит. Файлик каждый раз вытягивается заново. Оказалось, что

  • часть передаваемых параметров уникальна для каждого запроса. Там передается некая статистика о клиенте и служебная информация. Каждый раз новая.
  • при повторном запросе может быть использован другой storage-сервер.
По факту получается, что нужны более хитрые (regexp-based) алгоритмы идентификации ресурса, чем просто URI. Например для youtube URI выглядит так:
http://r12---sn-5hn7sb7k.c.youtube.com/videoplayback?algorithm=throttle-factor&
burst=40&cp=U0hUSlZMVl9NU0NONF9ORlpHOjM0RE5Ea0FhNzh0&expire=1355618689&factor=1.25&
fexp=922401%2C920704%2C912806%2C925703%2C928001%2C922403%2C922405%2C929901%2C913605
%2C913546%2C913556%2C920201%2C913302%2C919009%2C914903%2C911116%2C910221%2C901451%2C902556&
gcr=ua&id=d2e4d35a7a16e4c9&ip=62.205.155.193&ipbits=8&itag=35&key=yt1&ms=au&mt=1355594472
&mv=m&newshard=yes&
signature=B09349257DBD3FB48F1F4EC0C062F69E6311B60D.AB3F761505B087D3C0A56C250DEDE2EFB809F228&
source=youtube&sparams=algorithm%2Cburst%2Ccp%2Cfactor%2Cgcr%2Cid%2Cip%2Cipbits%2Citag%2Csource
%2Cupn%2Cexpire&sver=3&upn=kUlkGtNR8a4&ptk=youtube_multi&cpn=CYOwEfaq23k1BTh7
но во всем этом безобразии ключевым моментом является
*.youtube\.com\/videoplayback\?.*&id=(\d*)&.*

Нашел в squid.conf такую опцию: url_rewrite_program. Позволяет анализировать запрос внешней программой и если что - перенаправлять на другой источник. Таким образом можно повысить вероятность кеш-попадания. Получается, что можно написать модуль, который будет отдельно извлекать идентификатор ресурса и если ресурс с таким идентификатором уже спрашивали, то подставлять URI, использовавшийся в старом запросе. Правда, есть подводный камень - старый адрес может устареть раньше, чем мы думаем. Кроме того, флаги управления кешированием могут помешать ролику попасть в кеш на достаточно длительное время. И такую ситуацию одним url_rewrite_program не исправить. По идее, нужен специальный плагин, который будет работать сразу с URI и caching options.

Также, в Squid 2.7 в squid.conf есть опция storeurl_rewrite_program. Решает в точности нашу задачу - на основании анализа URL'а генерируется идентификатор ресурса, который и используется в дальнейшем для проверки наличия объекта в кеше. По-прежнему, флаги управления кешированием могут помешать файлу попасть в кеш, но это решаемо.

Note: в Squid 3.x такого нет. Когда будет - неизвестно, портировать сложно, т.к. Squid 3.0 фактически переписан заново на C++ с ООП в полный рост. Также отмечу, что в 2.x нет поддержки IPv6, А в 3.x - уже есть.

Нашел почти готовую реализацию с nabble.com by Lucas Diaz

При попытке применить оказалось, что нужно слегка подправить squid.conf, для принудительного кеширования видеопотоков и редко меняющихся картинок. Многие сайты (умышленно ?) используют директивы, запрещающие кеширование.

#	usage: refresh_pattern [-i] regex min percent max [options]
#	The refresh_pattern lines are checked in the order listed here.
refresh_pattern ^ftp:		1440	20%	10080
refresh_pattern ^gopher:	1440	0%	1440
refresh_pattern youtube.*videoplay  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern youtube.*get_video  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern google.*videoplay   14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern googlevideo.*get_video  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern ytimg\.com\/.*\.(jpg|jpeg|gif|png|ico|mp3|flv|mp4)  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern (mt|kh|pap).*\.google\.com  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern (mt|kh|pap).*\.googleapis\.com  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern s\d+\.dotua\.org\/fsua_items.*\.(jpg|jpeg|gif|png|ico|mp3|flv|mp4)  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern .*static\.video\.yandex\.ru\/swf\/.*&r=.*  14400   90%     24400   ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern vec.*\.maps\.yandex\.net\/tiles\?	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern static.*\.maps\.yandex\.	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern pvec.*\.maps\.yandex\.net	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern lrs\.maps\.yandex\.net\/tiles\?		14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern yandex\.st\/.*(jpg|jpeg|gif|png|ico|mp3|flv|mp4)		14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern static\.video\.yandex\.net\/.*(jpg|jpeg|gif|png|ico|mp3|flv|mp4).*		14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private ignore-auth
refresh_pattern .*ecn\.dynamic.*\.tiles\.virtualearth\.net\/comp   14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern fbcdn\.net.*\.(jpg|jpeg|gif|png|ico|mp3|flv)	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern static\.ak\.fbcdn\.net.*\.(jpg|jpeg|gif|png|ico|mp3|flv)	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern (st|cs)\d+\.vk\.me\/.*\.(jpg|jpeg|gif|png|ico|mp3|flv|mp4)	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern img\d+.slando\.ua\/.*\.(jpg|jpeg|gif|png|ico|mp3|flv)	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern .*s\d*\.staticclassifieds\.com\/static	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern \.vkadre\.ru\/assets\/.*\.(jpg|jpeg|gif|png|ico|mp3|flv|mp4)	14400	90%	20080 ignore-no-cache override-expire override-lastmod ignore-reload ignore-private
refresh_pattern .*\.(css)$	1440	90%	1440 ignore-no-cache override-expire override-lastmod ignore-private
refresh_pattern .*\.(js)$	1440	90%	1440 ignore-private
refresh_pattern -i (/cgi-bin/|\?) 10	20%	120
refresh_pattern .		10	20%	4320
#	see also refresh_pattern for a more selective approach.

cache_mem 400 MB
maximum_object_size_in_memory 4 MB
maximum_object_size 32 MB
read_ahead_gap 64 KB
range_offset_limit -1

и добавить в rewrite.pl правила объединения объектов по именам.


И вот еще одно решение: yt-cache

Результаты

Cделали исследование кешируемости трафика. Подопытные - несколько офисных машинок + 2 мои рабочие. Исходные данные:

cache_dir aufs /var/cache 256 32 256
cache_mem 400 MB
maximum_object_size_in_memory 4 MB
maximum_object_size 32 MB

За 10 дней через проксю пробежало 3.1Гб. Из них 88% (!!!) cs***.vk.me. Вконтактик (!) И еще 2% по его другим доменным именам. Я просто офигел изрядно удивился. Следующим был youtube. 4%. Остальное - несущественно. А вообще, результаты интересные. При имеющихся настройках (агрессивный кеш). спасли 38% трафика. Что соответствует степени кешируемости vk (37%) На youtube удалось получить 94% экономии. А в среднем по больнице (на сайтах, для которых не было спец-настроек) получили 31%. PS. без спец-настроек vk и youtube практически не кешируются (менее 5%)

В следующие 6 дней добавилось еще несколько машинок и результат поменялся. Основную часть (2.8 Гб) составил тяжелый мультимедийный контент, который кешированию не подлежал в принципе (лимит 32Мб), а также одноразовые загрузки роликов и музыка из vk. Для оставшихся 300Мб соотношение кеш-попаданий и общего числа обращений сохранилось на уровне 33%. Вывод - для multimedia это все имеет смысл только при большом количестве клиентов и очень большом кеше. На серфинге экономим треть, но он составляет около 10% от общего трафика. При этом обнаружилось, что мультимедийный контент vk практически не кешировался (ошибка в настройках). Так что продолжение следует.

Эффективность "Склеивания" URL'ов (rewrite.pl)
HostJoin-hitsHitsTotalEfficiency, %
videos.youtube.INTERNAL18181735368150
vk.me.INTERNAL8840148918
files.facebook.INTERNAL33127550
vec.yandex.INTERNAL018022390
  • Host - Условное имя объединяемой группы имен.
  • Join-hits - Новый URL был трансформирован, и благодаря этому был загружен из кеша.
  • Hits - URL уже был ранее запрошен.

Отдельно были исследованы логи локальных проксей пользовательских машин. В отличие от общей прокси на них настроена блокировка баннеров и счетчиков. Тяжелый контент тоже был отделен от котлет. Результат - все те же 33% в среднем по больнице.

Герои и аномалии

Почему есть смысл отрубить Safe Browsing ? Потому что он жрет почти половину всего канала! Прокси уменьшила расход вдвое, но все же...

Domain Cache/Refresh
traffic
Cache/Refresh
hits
Total trafficTotal hits Traffic
Efficiency, %
Hit
Efficiency, %
Original cache
efficiency
Weight
sb.google.com ~1Gb880 000 ~2Gb930 000 95560% 48%

Полезный ресурс, содержащий на удивление много реклам/баннеров/счечиков

Domain Blocked
traffic
Blocked
hits
Total trafficTotal hits Traffic
Efficiency, %
Hit
Efficiency, %
Original cache
efficiency
local.com.ua ~4Mb3270 ~5Mb3340 00

Главные потребители трафика, они же наиболее эффективно кешируемые (только принудительно!):

Domain Traffic
Efficiency, %
Hit
Efficiency, %
Original cache
efficiency
Weight
cs*.vk.me 23370% 88%
youtube.com 78940% 4%
st*.vk.me 99980% 1%

Другие знакомые ресурсы

Domain Traffic
Efficiency, %
Hit
Efficiency, %
Original cache
efficiency
Weight
vec*.maps.yandex.net 4544 1%
api-maps.yandex.ru 4544 1%
photos-*.fbcdn.net 21 1%
www.google.com 1077% 1%
en.wikipedia.org 1522%
video*.vkadre.ru 75500% 1%
platform.twitter.com 753737%

Выводы, что ли...
В общем объеме трафика ISP на HTTP приходится около 10-30%. HTTPS - около 2%. Из этих 10-30% на web-серфинг приходится тоже ~10%. Т.е. заморачиваться ради экономии 1-2% смысла нет. А для улучшения качества сервиса, повышения доступности ресурсов (типа заботимся о пользователях) - смысл есть. В случае перегрузки канала или самого ресурса - тоже. Скорость загрузки страницы бросается в глаза сильнее, чем все остальное.

Отдельный момент - процент запросов, обработанных proxy без обращения к внешним серверам, в т.ч. без REFRESH_HIT, поскольку время отклика имеет значение. Отработали половину запросов - страничка в 2 раза быстрее загрузилась. Клиент счастлив.

А для самих контент-провайдеров есть, наверное, повод задуматься. Если принудительный кеш экономит от 30 до 95 процентов полосы, может это повод таки позволить клиентам кешировать данные ?

И по-хорошему, помимо деления на статику и динамику, стоило бы разделить статические данные на легкие, тяжелые, да еще и признак real-time'овости ввести.

History

После множества обновлений и дополнений настройки Squid уехали на отдельную страницу.

2013.09.16

Первая версия.

2012.12.16


2012.12.16, updated 2013.09.16

См. также:




Mail to alterX@alter.org.ua (remove X)  
<< Back Автор: Alter (Александр А. Телятников) Сервер: Apache+PHP под FBSD © 2002-2017