«Вечная статика»оптимизация отдачи контента<br />Сергей Скворцов<br />2011-04-26<br />
I. Теория<br />3<br />
Стороны и связь<br />Браузер<br />отображение/рендеринг страниц/данных<br />Протокол<br />передача данных: запрос-ответ ил...
Скорость показа контента<br />Скорость отображения в браузере<br />Скорость передачи по сети<br />Скорость ответа от серве...
1)Скорость отображения в браузере<br />Рендеринг / вёрстка<br />Встраивание ресурсов/данных<br />Data URI, CSS sprites<br ...
1.1) Рендеринг/вёрстка<br />Корректный порядок указания ресурсов (JS/CSS)<br />Yahoo «Best Practices for Speeding Up Your ...
2)Скорость передачи по сети<br />Каналы…<br />… связность, распределение по странам, ДЦ<br />DNS-resolving<br />Уменьшение...
2)Скорость передачи по сети<br />Раздача с нескольких хостов<br />CDN;    DNS/geo-balancing, TCP anycast<br />Параллелизац...
2)Скорость передачи по сети<br />HTTP pipelining - не популярен<br />Дружим с proxy-servers, и ненавидим их<br />Кэширован...
3)Скорость ответа от сервера<br />Скорость генерации ответа<br />Уменьшение размера ответа<br />Уменьшение размера запроса...
3.1) Скорость генерации ответа<br />Хорошие frontend’ы<br />Быстрые серверы приложений (backend’ы)<br />Прогрессивная отда...
3.2) Уменьшение размера ответа<br />Сжатие ответа <br />ngx_http_gzip, ngx_http_gzip_static <br />mod_gzip, mod_deflate<br...
3.2) Уменьшение размера ответа<br />Оптимизация содержимого (minification) <br />Оптимизация JS/CSS <br />Closurecompiler,...
3.3) Уменьшение размера запроса<br />Отдача статики в другом домене <br />Чтобы не слать лишние заголовки: Cookie<br />Уме...
3.4) Уменьшение числа запросов<br />Кэширование контента на стороне браузера<br />Объединение стилей и скриптов (JS, CSS)<...
Итого<br />Всё вышеописанное можно использовать как checklist, варианты ответов:<br />Уже так делаем<br />Не делаем, потом...
II. Приём<br />18<br />
Как работает кэширование в HTTP<br />При первом запросе к ресурсу браузер:<br />Запоминает заголовки ответаLast-Modified и...
Как работает кэширование в HTTP<br />При втором запросе к серверу:<br />Если ресурс в локальном кэше – браузер делает вали...
Нюансы де-факто<br />По факту ETagиспользуетсядля статики так:<br />nginx: не вычисляет вообще<br />Apache:inode-size-time...
Проблемы этого дня<br />Заголовки ExpiresиCache-Control: max-age тупо не выставляют<br />56% запросов вообще не указывают ...
Проблемы этого дня<br />Поскольку нет expiration – каждый раз шлётся запрос (в надежде на 304 Not modified)<br />Но такой ...
Решение: выставлять expiration<br />Выставлять expiration для динамики несложно (семантику знает backend)<br />Но любой ко...
Версионирование<br />Наивный подход – добавлять «?» + timestamp: /favicon.ico?ver=3<br />Многие прокси серверы считают URL...
Версионирование: верный подход<br />Добавляем версию внутрь пути: /favicon_1303591683.ico<br />Версию можно брать из VCS, ...
Обработка внешних зависимостей<br />Делаем общий префикс /s/в URLах статики<br />Для всех шаблонов, которые ссылаются на в...
Применимость<br /><ul><li>Стоит применять для:</li></ul>Файлов стилей и скриптов (CSS, JS)<br />Картинок, являющихся часть...
Немного статистики:число запросов<br />
mime-types:по числу запросов<br />
mime-types:медиана размера ответа<br />
HTTP Archive:медиана размера ответа<br />http://httparchive.org/interesting.php#responsesizes<br />
33<br />III. Практика<br />
Htdocs layout<br />На файловой системе:<br />htdocs/<br />      frontend/<br />     eternal/<br />      backend/<br /><ul>...
eternal– «вечная» статика, отдаётся nginx
backend - шаблоны, используются в upstream</li></li></ul><li>VCS layout<br />В репозитории:<br />trunk/<br />htdocs-fronte...
Сборка пакетов: шаги<br />Checkout<br />Processing<br />Стадия «generate»<br />Стадия «preprocess»<br />Стадия «optimize»<...
Сборка пакетов – Processing<br />Стадия «generate»<br />Генерация новых файлов, на основе checkout’а<br />img2css– набор и...
Сборка пакетов – Processing<br />Стадия «optimize»<br />Оптимизация формата файла, с сохранением инварианта его семантики<...
Сборка пакетов – «вечная» статика<br />Конфигурация:<br /><handler<br />	name="eternal-static"<br />process_path="/a/"<br ...
Сборка пакетов – «вечная» статика<br />Сканируем директорию process_pathна предмет статических файлов с нужными расширения...
Сборка пакетов – «вечная» статика<br />В директории target_pathсоздаём соотв. версии статических файлов (и их gzipped-верс...
Сборка пакетов – «вечная» статика<br />Для статического файла, который не имеет зависимостей (в т.ч. тех, которые не раскр...
Сборка пакетов – «вечная» статика<br />Для статического файла, который имеет зависимости, ревизия вычисляется как md5( joi...
Сборка пакетов – «вечная» статика<br />Создаём файл /s/.mapping, который содержит строки с парами "статический файл", "веч...
Пример: www.openstat.ru<br /><!DOCTYPE HTML><html lang="ru"><head> <br /><title>Интернет-статистика и веб-аналитика | Open...
Установка пакетов<br />Файлы ставятся в share/htdocs/frontend<br />На этапе POST-INSTALL запускаем:<br />rsync -rlptgoD--c...
Установка пакетов<br />Также копируем вечную статику:<br />rsync -rlptgoD--checksum<br />htdocs/frontend/s/<br />htdocs/et...
Установка пакетов<br />Раскрываем(и атомарно замещаем) файлы шаблонов по списку из /s/.mapping:htdocs/backend<br />Посколь...
Конфигурация frontend’а<br />Пример для обычного веб-сервера:<br />location ^~ /s/   {<br />      alias   htdocs/eternal;<...
Соглашения<br />Соглашения для раскрываемых файлов:<br />Полное указание пути на ссылаемые файлы<br />В JS не использовать...
favicon<br /><ul><li>IE(и иные браузеры) всегда запрашивают /favicon.ico, если нет<link rel=”icon” …/></li></ul>Выдавать 4...
IV. Tips & tricks<br />52<br />
Битва за байты: заголовки<br />Заголовок Server:<br />Вообще-то его надо оставлять – это полезная статистика<br />https://...
Битва за байты: HTML5 vs. XHTML<br />
Используем TLS/SSL<br />TLS/SSL – уже не дорого в плане вычислений (CPU)<br />Отдельные аппаратные акселераторы уже не нуж...
Минусы TLS/SSL<br />Дополнительные 4+ IP пакета на handshake (размер public key имеет значение!)<br />Больший размер ответ...
Минусы TLS/SSL<br />Блокирование на OCSP (проверка сертификата сервера) = +N*100ms<br />FF3+;    IE* on Vista / Win7, …<br...
Минусы TLS/SSL<br />SSL + IE6/7+data:uriв HTML =«небезопасный ресурс»<br />Доля IE6 + IE7 в Рунете - 9%<br />SSL + отдача ...
Вопросы?(по теме доклада)<br />http://protey.ru/blog/2011/04/rit-2011.html<br />Сергей Скворцов<br />skv@protey.ru<br />59...
Upcoming SlideShare
Loading in …5
×

Eternal static (RIT 2011)

713 views

Published on

«Вечная статика» оптимизация отдачи контента

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
713
On SlideShare
0
From Embeds
0
Number of Embeds
31
Actions
Shares
0
Downloads
6
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Eternal static (RIT 2011)

  1. 1. «Вечная статика»оптимизация отдачи контента<br />Сергей Скворцов<br />2011-04-26<br />
  2. 2.
  3. 3. I. Теория<br />3<br />
  4. 4. Стороны и связь<br />Браузер<br />отображение/рендеринг страниц/данных<br />Протокол<br />передача данных: запрос-ответ или stream<br />Сервер<br />приём запросов, формирование и передача ответов<br />
  5. 5. Скорость показа контента<br />Скорость отображения в браузере<br />Скорость передачи по сети<br />Скорость ответа от сервера<br />
  6. 6. 1)Скорость отображения в браузере<br />Рендеринг / вёрстка<br />Встраивание ресурсов/данных<br />Data URI, CSS sprites<br />увеличивает размер ответа<br />AJAX, WebSockets<br />Отложенная загрузка;Prefetching<br />JavaScript: async/defer; post-load<br />
  7. 7. 1.1) Рендеринг/вёрстка<br />Корректный порядок указания ресурсов (JS/CSS)<br />Yahoo «Best Practices for Speeding Up Your Web Site»<br />Самоограничения: CSSexpressions<br />Прогрессивная вёрстка<br />см. StoyanStefanov (Yahoo) <br />Верстка независимыми блоками<br />см. Виталий Харисов (Яндекс) <br />Шаблоны на client-side (XSLT)<br />
  8. 8. 2)Скорость передачи по сети<br />Каналы…<br />… связность, распределение по странам, ДЦ<br />DNS-resolving<br />Уменьшение числа lookup’ов (число хостов, TTL)<br />Geo-balancing, IP anycast<br />Постоянные соединения<br />HTTP 1.0 keep-alive == HTTP 1.1 persistent<br />
  9. 9. 2)Скорость передачи по сети<br />Раздача с нескольких хостов<br />CDN; DNS/geo-balancing, TCP anycast<br />Параллелизация загрузки: default лимит у браузеров – не более 6 запросов на хост<br />JS-хостинги (для jQuery, YUI, …)<br />13% страниц используют Google Libraries API<br />Хорошо кэшируютсямежду сайтами<br />Privacy: источник Referer’ов для поисковиков<br />
  10. 10. 2)Скорость передачи по сети<br />HTTP pipelining - не популярен<br />Дружим с proxy-servers, и ненавидим их<br />Кэширование!<br />Их 10% запросов (оценка по Openstat.Trends)<br />«Над»-протоколы (HTTPS, SPDY)<br />HTTPS – безопасность, но overhead<br />SPDY – только Google, нет поддержки в nginx :)<br />
  11. 11. 3)Скорость ответа от сервера<br />Скорость генерации ответа<br />Уменьшение размера ответа<br />Уменьшение размера запроса<br />Уменьшение числа запросов<br />
  12. 12. 3.1) Скорость генерации ответа<br />Хорошие frontend’ы<br />Быстрые серверы приложений (backend’ы)<br />Прогрессивная отдача контента <br />flush()<br />Кэширование:<br />данных (memcached)<br />ответа (mod_cache*)<br />
  13. 13. 3.2) Уменьшение размера ответа<br />Сжатие ответа <br />ngx_http_gzip, ngx_http_gzip_static <br />mod_gzip, mod_deflate<br />Отложенная «подгрузка» JS, контента<br />Post-loading<br />
  14. 14. 3.2) Уменьшение размера ответа<br />Оптимизация содержимого (minification) <br />Оптимизация JS/CSS <br />Closurecompiler, YUI Compressor<br />Оптимизация графики<br />Оптимизация HTML<br />Пробелы, комментарии, default атрибуты, …<br />htmlcompressor,или при компиляции шаблонов <br />
  15. 15. 3.3) Уменьшение размера запроса<br />Отдача статики в другом домене <br />Чтобы не слать лишние заголовки: Cookie<br />Уменьшаем размер Cookie<br />FYI: максимальный суммарный размер на домен:<br />Firefox, Chrome - no limit<br />Opera, IE6 - 4096байт<br />IE8 - 10234байт<br />
  16. 16. 3.4) Уменьшение числа запросов<br />Кэширование контента на стороне браузера<br />Объединение стилей и скриптов (JS, CSS)<br />Объединение и внедрение картинок(CSS sprites, Data URI, MHTML)<br />ценой большего размера ответа<br />Избегать редиректов<br />
  17. 17. Итого<br />Всё вышеописанное можно использовать как checklist, варианты ответов:<br />Уже так делаем<br />Не делаем, потому что (программисты|админы) сказали что…<br />Не знали / совсем забыли – надо подумать<br />
  18. 18. II. Приём<br />18<br />
  19. 19. Как работает кэширование в HTTP<br />При первом запросе к ресурсу браузер:<br />Запоминает заголовки ответаLast-Modified и/ли ETag<br />Определяет сколько времени можно не обращаться к серверу, а использовать локальный кэш - на основе данных из заголовков:<br />Expires<br />Cache-Control<br />http://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/<br />
  20. 20. Как работает кэширование в HTTP<br />При втором запросе к серверу:<br />Если ресурс в локальном кэше – браузер делает валидацию – шлёт условный запрос:<br />If-Unmodified-Sinceи/ли If-None-Match<br />Если ресурс не менялся (304 Not modified):ждём опять expiration<br />
  21. 21. Нюансы де-факто<br />По факту ETagиспользуетсядля статики так:<br />nginx: не вычисляет вообще<br />Apache:inode-size-timestamp<br />IIS:Filetimestamp:ChangeNumber<br />Это не работает на кластере машин<br />inodeи ChangeNumberбудут разные<br />
  22. 22. Проблемы этого дня<br />Заголовки ExpiresиCache-Control: max-age тупо не выставляют<br />56% запросов вообще не указывают expiration<br />24% запросов может кэшироваться http://www.stevesouders.com/blog/2011/04/18/http-archive-max-ag/<br />Нопри этом есть статика – которая меняется редко:<br />CSS, JavaScript, картинки, Flash, иконки (!)<br />
  23. 23. Проблемы этого дня<br />Поскольку нет expiration – каждый раз шлётся запрос (в надежде на 304 Not modified)<br />Но такой запрос это:<br />Минимум 2 IP пакета<br />Время на ожидание ответа<br />Особенно печально ждать когда блокируемся на рендеринге<br />
  24. 24. Решение: выставлять expiration<br />Выставлять expiration для динамики несложно (семантику знает backend)<br />Но любой константный expiration для статики приводит к проблемам при обновлении сайта (новый дизайн, шаблоны, …)<br />Единый глобальный Expire - выставить нельзя<br />Выход: версионированиена уровне URI<br />
  25. 25. Версионирование<br />Наивный подход – добавлять «?» + timestamp: /favicon.ico?ver=3<br />Многие прокси серверы считают URL с «?» некэшируемым в принципе<br />Не учитываются зависимости внутри ресурса:<br />/style.css?ver=3ссылается внутри на /logo.png?ver=5<br />
  26. 26. Версионирование: верный подход<br />Добавляем версию внутрь пути: /favicon_1303591683.ico<br />Версию можно брать из VCS, но не каждый ресурс лежит в репозитории, он может создаваться при выкатке<br />Очевидный вариант – timestamp<br />Для файлов с зависимостями «наружу» – считаем версию с учётом зависимостей, пример:<br /> md5( timestamp + @versioned_dependencies_urls)<br />Экономим байты – используя Base64 URLSafe<br />
  27. 27. Обработка внешних зависимостей<br />Делаем общий префикс /s/в URLах статики<br />Для всех шаблонов, которые ссылаются на версионированную статику, обновляем ссылки<br />Всё! Статика стала вечной, поэтому:<br />location /s/ {<br />expires max;<br />gzip_static on;<br />}<br />
  28. 28. Применимость<br /><ul><li>Стоит применять для:</li></ul>Файлов стилей и скриптов (CSS, JS)<br />Картинок, являющихся частью дизайна/шаблона<br />Flash-объектов<br /><ul><li>Не надо применять для:</li></ul>Скачиваемых файлов (и подлежащих индексации)<br />Особо актуально:<br />Мобильные сайты<br />
  29. 29. Немного статистики:число запросов<br />
  30. 30. mime-types:по числу запросов<br />
  31. 31. mime-types:медиана размера ответа<br />
  32. 32. HTTP Archive:медиана размера ответа<br />http://httparchive.org/interesting.php#responsesizes<br />
  33. 33. 33<br />III. Практика<br />
  34. 34. Htdocs layout<br />На файловой системе:<br />htdocs/<br /> frontend/<br /> eternal/<br /> backend/<br /><ul><li>frontend - статика, отдаётся nginx
  35. 35. eternal– «вечная» статика, отдаётся nginx
  36. 36. backend - шаблоны, используются в upstream</li></li></ul><li>VCS layout<br />В репозитории:<br />trunk/<br />htdocs-frontend/<br /> a/<br />css/<br />img/<br />js/<br />htdocs-backend/<br />
  37. 37. Сборка пакетов: шаги<br />Checkout<br />Processing<br />Стадия «generate»<br />Стадия «preprocess»<br />Стадия «optimize»<br />Стадия «produce»<br />Генерация «вечной статики» (кладём в /s/)<br />Packing distfiles<br />
  38. 38. Сборка пакетов – Processing<br />Стадия «generate»<br />Генерация новых файлов, на основе checkout’а<br />img2css– набор иконок в один CSS файл<br />Стадия «preprocess»<br />Изменение содержимого файла, и/ли метаданных о нём<br />inline-includes– объединение файлов<br />CSS: раскрытие @import<br />JavaScript: раскрытие _include_js()<br />
  39. 39. Сборка пакетов – Processing<br />Стадия «optimize»<br />Оптимизация формата файла, с сохранением инварианта его семантики<br />yuicompressor– JS/CSS minification<br />Стадия «produce»<br />Генерация других файлов на основе итоговых<br />gzip_static– создание сжатой версии статики<br />
  40. 40. Сборка пакетов – «вечная» статика<br />Конфигурация:<br /><handler<br /> name="eternal-static"<br />process_path="/a/"<br />target_path="/s/"<br />match_ext="gif icojpg pngswfjscss"<br />expand_ext="jscss"<br />/><br />
  41. 41. Сборка пакетов – «вечная» статика<br />Сканируем директорию process_pathна предмет статических файлов с нужными расширениями<br />Обрабатываем раскрываемые файлы (*.js *.css) на предмет ссылок на другие найденные ранее статические файлы<br />Строим граф зависимостей<br />
  42. 42. Сборка пакетов – «вечная» статика<br />В директории target_pathсоздаём соотв. версии статических файлов (и их gzipped-версий, если у файлов был handlergzip_static)<br />Итоговый файл будет называтьсяfilename_revision.ext, где revision – ревизия файла<br />/a/file.txt /s/file_REVISION.txt<br />
  43. 43. Сборка пакетов – «вечная» статика<br />Для статического файла, который не имеет зависимостей (в т.ч. тех, которые не раскрываются вообще, типа картинок), ревизия равна mtime<br />VCS ревизия может быть недоступна, если файл генерировался.<br />При генерации файлов mtimeфинального файла всегда равен максимальному mtimeего исходных файлов<br />
  44. 44. Сборка пакетов – «вечная» статика<br />Для статического файла, который имеет зависимости, ревизия вычисляется как md5( join('0', mtime, sort@eternal_static_deps) ) - т.е. создаётся семантически уникальная ревизия файла.<br />Жёсткое создание ревизии (md5 от тела файла) не используется, чтобы при изменениях контента, которые семантически инвариантны (например, применён новый алгоритм оптимизации/obfuscation файлов) не создавалась новая ревизия.<br />
  45. 45. Сборка пакетов – «вечная» статика<br />Создаём файл /s/.mapping, который содержит строки с парами "статический файл", "вечно-статический файл":<br />/a/js/base.js /s/js/base_iv6uTQ.js<br />/s/css/main.css /s/css/main_msy5mT8H-Ak6hBAsce-30w.css<br />
  46. 46. Пример: www.openstat.ru<br /><!DOCTYPE HTML><html lang="ru"><head> <br /><title>Интернет-статистика и веб-аналитика | Openstat: Независимая аналитика</title> <br /><link rel="stylesheet" type="text/css" href="/s/css/main_msy5mT8H-Ak6hBAsce-30w.css" /> <br /><script type="text/javascript" src="/s/js/base_iv6uTQ.js"></script><br />
  47. 47. Установка пакетов<br />Файлы ставятся в share/htdocs/frontend<br />На этапе POST-INSTALL запускаем:<br />rsync -rlptgoD--checksum--delete-after <br />share/htdocs/frontend<br />htdocs/frontend<br />Это делается для того, чтобы при удалении пакета в htdocs/frontendчто-то оставалось<br />
  48. 48. Установка пакетов<br />Также копируем вечную статику:<br />rsync -rlptgoD--checksum<br />htdocs/frontend/s/<br />htdocs/eternal<br />В htdocs/eternalфайлы никогда не удаляются!<br />
  49. 49. Установка пакетов<br />Раскрываем(и атомарно замещаем) файлы шаблонов по списку из /s/.mapping:htdocs/backend<br />Поскольку директория /a/также ставится, то задержка в раскрытии файлов, равно как их нераскрытиене влияет фатально на работу сайта - просто запросы пойдут к "менее вечной" статике.<br />
  50. 50. Конфигурация frontend’а<br />Пример для обычного веб-сервера:<br />location ^~ /s/ {<br /> alias htdocs/eternal;<br />gzip_static on;<br /> expires max;<br />}<br />
  51. 51. Соглашения<br />Соглашения для раскрываемых файлов:<br />Полное указание пути на ссылаемые файлы<br />В JS не использовать составление URLиз частей , прописывать в коде полностью(как hash)<br />
  52. 52. favicon<br /><ul><li>IE(и иные браузеры) всегда запрашивают /favicon.ico, если нет<link rel=”icon” …/></li></ul>Выдавать 404 – не выход, поскольку запросы всё равно будут идти<br />Правильно так:<br />location = /favicon.ico {<br />root /path/to/htdocs;<br />expires 30d;<br />}<br />
  53. 53. IV. Tips & tricks<br />52<br />
  54. 54. Битва за байты: заголовки<br />Заголовок Server:<br />Вообще-то его надо оставлять – это полезная статистика<br />https://www.openstat.ru/counter/trends/<br />Но надо убирать из него длинных список скомпилированных модулей:<br />Server: Apache/1.3.27 (Unix) mru_xml/0.471 gorgona/2.1 mod_jk/1.2.4 mod_ruby/1.0.7 Ruby/1.6.8 mod_mrim/0.17<br />Также убирать прочие «гордые» заголовки:<br />X-Powered-By: PHP/5.2.6-1+lenny9<br />
  55. 55. Битва за байты: HTML5 vs. XHTML<br />
  56. 56. Используем TLS/SSL<br />TLS/SSL – уже не дорого в плане вычислений (CPU)<br />Отдельные аппаратные акселераторы уже не нужны<br />CPU Intel Core i5+ поддерживают AES instruction set<br />Privacy & confidentiality – всегда популярно среди параноиков<br />https://gmail.com, https://encrypted.google.com<br />Цена сертификата Thawte - всего $45<br />
  57. 57. Минусы TLS/SSL<br />Дополнительные 4+ IP пакета на handshake (размер public key имеет значение!)<br />Больший размер ответов<br />record header, padding (если block cipher)<br />При тщательно подобранном размере ответа ресурса (чтобы, скажем, влез в 1 IP пакет),применение SSL может повлечь +1 IP пакет<br />
  58. 58. Минусы TLS/SSL<br />Блокирование на OCSP (проверка сертификата сервера) = +N*100ms<br />FF3+; IE* on Vista / Win7, …<br />Решение - OCSP stapling<br />Не работает с chained certs<br />+~1KB данных (OCSP ответ)<br />Есть в Apache, нет в nginx<br />
  59. 59. Минусы TLS/SSL<br />SSL + IE6/7+data:uriв HTML =«небезопасный ресурс»<br />Доля IE6 + IE7 в Рунете - 9%<br />SSL + отдача статики параллельно с нескольких хостов= дополнительные затраты на сертификаты<br />либо несколько сертификатов для разных хостов (www.foobar.ru, img.foobar.ru)<br />либо условно дорогой wildcard(*.foobar.ru)<br />
  60. 60. Вопросы?(по теме доклада)<br />http://protey.ru/blog/2011/04/rit-2011.html<br />Сергей Скворцов<br />skv@protey.ru<br />59<br />

×