4. Стороны и связь Браузер отображение/рендеринг страниц/данных Протокол передача данных: запрос-ответ или stream Сервер приём запросов, формирование и передача ответов
5. Скорость показа контента Скорость отображения в браузере Скорость передачи по сети Скорость ответа от сервера
6. 1)Скорость отображения в браузере Рендеринг / вёрстка Встраивание ресурсов/данных Data URI, CSS sprites увеличивает размер ответа AJAX, WebSockets Отложенная загрузка;Prefetching JavaScript: async/defer; post-load
7. 1.1) Рендеринг/вёрстка Корректный порядок указания ресурсов (JS/CSS) Yahoo «Best Practices for Speeding Up Your Web Site» Самоограничения: CSSexpressions Прогрессивная вёрстка см. StoyanStefanov (Yahoo) Верстка независимыми блоками см. Виталий Харисов (Яндекс) Шаблоны на client-side (XSLT)
8. 2)Скорость передачи по сети Каналы… … связность, распределение по странам, ДЦ DNS-resolving Уменьшение числа lookup’ов (число хостов, TTL) Geo-balancing, IP anycast Постоянные соединения HTTP 1.0 keep-alive == HTTP 1.1 persistent
9. 2)Скорость передачи по сети Раздача с нескольких хостов CDN; DNS/geo-balancing, TCP anycast Параллелизация загрузки: default лимит у браузеров – не более 6 запросов на хост JS-хостинги (для jQuery, YUI, …) 13% страниц используют Google Libraries API Хорошо кэшируютсямежду сайтами Privacy: источник Referer’ов для поисковиков
10. 2)Скорость передачи по сети HTTP pipelining - не популярен Дружим с proxy-servers, и ненавидим их Кэширование! Их 10% запросов (оценка по Openstat.Trends) «Над»-протоколы (HTTPS, SPDY) HTTPS – безопасность, но overhead SPDY – только Google, нет поддержки в nginx :)
15. 3.3) Уменьшение размера запроса Отдача статики в другом домене Чтобы не слать лишние заголовки: Cookie Уменьшаем размер Cookie FYI: максимальный суммарный размер на домен: Firefox, Chrome - no limit Opera, IE6 - 4096байт IE8 - 10234байт
16. 3.4) Уменьшение числа запросов Кэширование контента на стороне браузера Объединение стилей и скриптов (JS, CSS) Объединение и внедрение картинок(CSS sprites, Data URI, MHTML) ценой большего размера ответа Избегать редиректов
17. Итого Всё вышеописанное можно использовать как checklist, варианты ответов: Уже так делаем Не делаем, потому что (программисты|админы) сказали что… Не знали / совсем забыли – надо подумать
19. Как работает кэширование в HTTP При первом запросе к ресурсу браузер: Запоминает заголовки ответаLast-Modified и/ли ETag Определяет сколько времени можно не обращаться к серверу, а использовать локальный кэш - на основе данных из заголовков: Expires Cache-Control http://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/
20. Как работает кэширование в HTTP При втором запросе к серверу: Если ресурс в локальном кэше – браузер делает валидацию – шлёт условный запрос: If-Unmodified-Sinceи/ли If-None-Match Если ресурс не менялся (304 Not modified):ждём опять expiration
21. Нюансы де-факто По факту ETagиспользуетсядля статики так: nginx: не вычисляет вообще Apache:inode-size-timestamp IIS:Filetimestamp:ChangeNumber Это не работает на кластере машин inodeи ChangeNumberбудут разные
22. Проблемы этого дня Заголовки ExpiresиCache-Control: max-age тупо не выставляют 56% запросов вообще не указывают expiration 24% запросов может кэшироваться http://www.stevesouders.com/blog/2011/04/18/http-archive-max-ag/ Нопри этом есть статика – которая меняется редко: CSS, JavaScript, картинки, Flash, иконки (!)
23. Проблемы этого дня Поскольку нет expiration – каждый раз шлётся запрос (в надежде на 304 Not modified) Но такой запрос это: Минимум 2 IP пакета Время на ожидание ответа Особенно печально ждать когда блокируемся на рендеринге
24. Решение: выставлять expiration Выставлять expiration для динамики несложно (семантику знает backend) Но любой константный expiration для статики приводит к проблемам при обновлении сайта (новый дизайн, шаблоны, …) Единый глобальный Expire - выставить нельзя Выход: версионированиена уровне URI
25. Версионирование Наивный подход – добавлять «?» + timestamp: /favicon.ico?ver=3 Многие прокси серверы считают URL с «?» некэшируемым в принципе Не учитываются зависимости внутри ресурса: /style.css?ver=3ссылается внутри на /logo.png?ver=5
26. Версионирование: верный подход Добавляем версию внутрь пути: /favicon_1303591683.ico Версию можно брать из VCS, но не каждый ресурс лежит в репозитории, он может создаваться при выкатке Очевидный вариант – timestamp Для файлов с зависимостями «наружу» – считаем версию с учётом зависимостей, пример: md5( timestamp + @versioned_dependencies_urls) Экономим байты – используя Base64 URLSafe
27. Обработка внешних зависимостей Делаем общий префикс /s/в URLах статики Для всех шаблонов, которые ссылаются на версионированную статику, обновляем ссылки Всё! Статика стала вечной, поэтому: location /s/ { expires max; gzip_static on; }
38. Сборка пакетов – Processing Стадия «generate» Генерация новых файлов, на основе checkout’а img2css– набор иконок в один CSS файл Стадия «preprocess» Изменение содержимого файла, и/ли метаданных о нём inline-includes– объединение файлов CSS: раскрытие @import JavaScript: раскрытие _include_js()
39. Сборка пакетов – Processing Стадия «optimize» Оптимизация формата файла, с сохранением инварианта его семантики yuicompressor– JS/CSS minification Стадия «produce» Генерация других файлов на основе итоговых gzip_static– создание сжатой версии статики
41. Сборка пакетов – «вечная» статика Сканируем директорию process_pathна предмет статических файлов с нужными расширениями Обрабатываем раскрываемые файлы (*.js *.css) на предмет ссылок на другие найденные ранее статические файлы Строим граф зависимостей
42. Сборка пакетов – «вечная» статика В директории target_pathсоздаём соотв. версии статических файлов (и их gzipped-версий, если у файлов был handlergzip_static) Итоговый файл будет называтьсяfilename_revision.ext, где revision – ревизия файла /a/file.txt /s/file_REVISION.txt
43. Сборка пакетов – «вечная» статика Для статического файла, который не имеет зависимостей (в т.ч. тех, которые не раскрываются вообще, типа картинок), ревизия равна mtime VCS ревизия может быть недоступна, если файл генерировался. При генерации файлов mtimeфинального файла всегда равен максимальному mtimeего исходных файлов
44. Сборка пакетов – «вечная» статика Для статического файла, который имеет зависимости, ревизия вычисляется как md5( join('', mtime, sort@eternal_static_deps) ) - т.е. создаётся семантически уникальная ревизия файла. Жёсткое создание ревизии (md5 от тела файла) не используется, чтобы при изменениях контента, которые семантически инвариантны (например, применён новый алгоритм оптимизации/obfuscation файлов) не создавалась новая ревизия.
45. Сборка пакетов – «вечная» статика Создаём файл /s/.mapping, который содержит строки с парами "статический файл", "вечно-статический файл": /a/js/base.js /s/js/base_iv6uTQ.js /s/css/main.css /s/css/main_msy5mT8H-Ak6hBAsce-30w.css
47. Установка пакетов Файлы ставятся в share/htdocs/frontend На этапе POST-INSTALL запускаем: rsync -rlptgoD--checksum--delete-after share/htdocs/frontend htdocs/frontend Это делается для того, чтобы при удалении пакета в htdocs/frontendчто-то оставалось
48. Установка пакетов Также копируем вечную статику: rsync -rlptgoD--checksum htdocs/frontend/s/ htdocs/eternal В htdocs/eternalфайлы никогда не удаляются!
49. Установка пакетов Раскрываем(и атомарно замещаем) файлы шаблонов по списку из /s/.mapping:htdocs/backend Поскольку директория /a/также ставится, то задержка в раскрытии файлов, равно как их нераскрытиене влияет фатально на работу сайта - просто запросы пойдут к "менее вечной" статике.
50. Конфигурация frontend’а Пример для обычного веб-сервера: location ^~ /s/ { alias htdocs/eternal; gzip_static on; expires max; }
51. Соглашения Соглашения для раскрываемых файлов: Полное указание пути на ссылаемые файлы В JS не использовать составление URLиз частей , прописывать в коде полностью(как hash)
54. Битва за байты: заголовки Заголовок Server: Вообще-то его надо оставлять – это полезная статистика https://www.openstat.ru/counter/trends/ Но надо убирать из него длинных список скомпилированных модулей: 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 Также убирать прочие «гордые» заголовки: X-Powered-By: PHP/5.2.6-1+lenny9
56. Используем TLS/SSL TLS/SSL – уже не дорого в плане вычислений (CPU) Отдельные аппаратные акселераторы уже не нужны CPU Intel Core i5+ поддерживают AES instruction set Privacy & confidentiality – всегда популярно среди параноиков https://gmail.com, https://encrypted.google.com Цена сертификата Thawte - всего $45
57. Минусы TLS/SSL Дополнительные 4+ IP пакета на handshake (размер public key имеет значение!) Больший размер ответов record header, padding (если block cipher) При тщательно подобранном размере ответа ресурса (чтобы, скажем, влез в 1 IP пакет),применение SSL может повлечь +1 IP пакет
58. Минусы TLS/SSL Блокирование на OCSP (проверка сертификата сервера) = +N*100ms FF3+; IE* on Vista / Win7, … Решение - OCSP stapling Не работает с chained certs +~1KB данных (OCSP ответ) Есть в Apache, нет в nginx
59. Минусы TLS/SSL SSL + IE6/7+data:uriв HTML =«небезопасный ресурс» Доля IE6 + IE7 в Рунете - 9% SSL + отдача статики параллельно с нескольких хостов= дополнительные затраты на сертификаты либо несколько сертификатов для разных хостов (www.foobar.ru, img.foobar.ru) либо условно дорогой wildcard(*.foobar.ru)
60. Вопросы?(по теме доклада) http://protey.ru/blog/2011/04/rit-2011.html Сергей Скворцов skv@protey.ru 59