«Вечная статика»оптимизация отдачи контентаСергей Скворцов2011-04-26
I. Теория3
Стороны и связьБраузеротображение/рендеринг страниц/данныхПротоколпередача данных: запрос-ответ или streamСерверприём запросов, формирование и передача ответов
Скорость показа контентаСкорость отображения в браузереСкорость передачи по сетиСкорость ответа от сервера
1)Скорость отображения в браузереРендеринг / вёрсткаВстраивание ресурсов/данныхData URI, CSS spritesувеличивает размер ответаAJAX, WebSocketsОтложенная загрузка;PrefetchingJavaScript: async/defer; post-load
1.1) Рендеринг/вёрсткаКорректный порядок указания ресурсов (JS/CSS)Yahoo «Best Practices for Speeding Up Your Web Site»Самоограничения: CSSexpressionsПрогрессивная вёрсткасм. StoyanStefanov (Yahoo) Верстка независимыми блокамисм. Виталий Харисов (Яндекс) Шаблоны на client-side (XSLT)
2)Скорость передачи по сетиКаналы…… связность, распределение по странам, ДЦDNS-resolvingУменьшение числа lookup’ов (число хостов, TTL)Geo-balancing, IP anycastПостоянные соединенияHTTP 1.0 keep-alive  == HTTP 1.1 persistent
2)Скорость передачи по сетиРаздача с нескольких хостовCDN;    DNS/geo-balancing, TCP anycastПараллелизация загрузки: default лимит у браузеров – не более 6 запросов на хостJS-хостинги (для jQuery, YUI, …)13% страниц используют Google Libraries APIХорошо кэшируютсямежду сайтамиPrivacy: источник Referer’ов для поисковиков
2)Скорость передачи по сетиHTTP pipelining - не популяренДружим с proxy-servers, и ненавидим ихКэширование!Их 10% запросов (оценка по Openstat.Trends)«Над»-протоколы (HTTPS, SPDY)HTTPS – безопасность, но overheadSPDY – только Google, нет поддержки в nginx :)
3)Скорость ответа от сервераСкорость генерации ответаУменьшение размера ответаУменьшение размера запросаУменьшение числа запросов
3.1) Скорость генерации ответаХорошие frontend’ыБыстрые серверы приложений (backend’ы)Прогрессивная отдача контента flush()Кэширование:данных (memcached)ответа (mod_cache*)
3.2) Уменьшение размера ответаСжатие ответа ngx_http_gzip, ngx_http_gzip_static mod_gzip, mod_deflateОтложенная «подгрузка» JS, контентаPost-loading
3.2) Уменьшение размера ответаОптимизация содержимого (minification) Оптимизация JS/CSS Closurecompiler, YUI CompressorОптимизация графикиОптимизация HTMLПробелы, комментарии, default атрибуты, …htmlcompressor,или при компиляции шаблонов 
3.3) Уменьшение размера запросаОтдача статики в другом домене Чтобы не слать лишние заголовки: CookieУменьшаем размер CookieFYI: максимальный суммарный размер на домен:Firefox, Chrome - no limitOpera, IE6 - 4096байтIE8 - 10234байт
3.4) Уменьшение числа запросовКэширование контента на стороне браузераОбъединение стилей и скриптов (JS, CSS)Объединение и внедрение картинок(CSS sprites, Data URI, MHTML)ценой большего размера ответаИзбегать редиректов
ИтогоВсё вышеописанное можно использовать как checklist, варианты ответов:Уже так делаемНе делаем, потому что (программисты|админы) сказали что…Не знали / совсем забыли – надо подумать
II. Приём18
Как работает кэширование в HTTPПри первом запросе к ресурсу браузер:Запоминает заголовки ответаLast-Modified и/ли ETagОпределяет сколько времени можно не обращаться к серверу, а использовать локальный кэш - на основе данных из заголовков:ExpiresCache-Controlhttp://www.w3.org/Protocols/HTTP/1.1/rfc2616bis/
Как работает кэширование в HTTPПри втором запросе к серверу:Если ресурс в локальном кэше – браузер делает валидацию – шлёт условный запрос:If-Unmodified-Sinceи/ли If-None-MatchЕсли ресурс не менялся (304 Not modified):ждём опять expiration
Нюансы де-фактоПо факту ETagиспользуетсядля статики так:nginx: не вычисляет вообщеApache:inode-size-timestampIIS:Filetimestamp:ChangeNumberЭто не работает на кластере машинinodeи ChangeNumberбудут разные
Проблемы этого дняЗаголовки ExpiresиCache-Control: max-age тупо не выставляют56% запросов вообще не указывают expiration24% запросов может кэшироваться http://www.stevesouders.com/blog/2011/04/18/http-archive-max-ag/Нопри этом есть статика – которая меняется редко:CSS, JavaScript, картинки, Flash, иконки (!)
Проблемы этого дняПоскольку нет expiration – каждый раз шлётся запрос (в надежде на 304 Not modified)Но такой запрос это:Минимум 2 IP пакетаВремя на ожидание ответаОсобенно печально ждать когда блокируемся на рендеринге
Решение: выставлять expirationВыставлять expiration для динамики несложно (семантику знает backend)Но любой константный expiration для статики приводит к проблемам при обновлении сайта (новый дизайн, шаблоны, …)Единый глобальный Expire - выставить нельзяВыход: версионированиена уровне URI
ВерсионированиеНаивный подход – добавлять «?» + timestamp: /favicon.ico?ver=3Многие прокси серверы считают URL с «?» некэшируемым в принципеНе учитываются зависимости внутри ресурса:/style.css?ver=3ссылается внутри на /logo.png?ver=5
Версионирование: верный подходДобавляем версию внутрь пути: /favicon_1303591683.icoВерсию можно брать из VCS, но не каждый ресурс лежит в репозитории, он может создаваться при выкаткеОчевидный вариант – timestampДля файлов с зависимостями «наружу» – считаем версию с учётом зависимостей, пример:	md5( timestamp + @versioned_dependencies_urls)Экономим байты – используя Base64 URLSafe
Обработка внешних зависимостейДелаем общий префикс /s/в URLах статикиДля всех шаблонов, которые ссылаются на версионированную статику, обновляем ссылкиВсё! Статика стала вечной, поэтому:location /s/ {expires max;gzip_static on;}
ПрименимостьСтоит применять для:Файлов стилей и скриптов (CSS, JS)Картинок, являющихся частью дизайна/шаблонаFlash-объектовНе надо применять для:Скачиваемых файлов (и подлежащих индексации)Особо актуально:Мобильные сайты
Немного статистики:число запросов
mime-types:по числу запросов
mime-types:медиана размера ответа
HTTP Archive:медиана размера ответаhttp://httparchive.org/interesting.php#responsesizes
33III. Практика
Htdocs layoutНа файловой системе:htdocs/      frontend/     eternal/      backend/frontend - статика, отдаётся nginx
eternal– «вечная» статика, отдаётся nginx
backend - шаблоны, используются в upstreamVCS layoutВ репозитории:trunk/htdocs-frontend/                     a/css/img/js/htdocs-backend/
Сборка пакетов: шагиCheckoutProcessingСтадия «generate»Стадия «preprocess»Стадия «optimize»Стадия «produce»Генерация «вечной статики» (кладём в /s/)Packing distfiles
Сборка пакетов – ProcessingСтадия «generate»Генерация новых файлов, на основе checkout’аimg2css– набор иконок в один CSS файлСтадия «preprocess»Изменение содержимого файла, и/ли метаданных о нёмinline-includes– объединение файловCSS: раскрытие @importJavaScript: раскрытие _include_js()
Сборка пакетов – ProcessingСтадия «optimize»Оптимизация формата файла, с сохранением инварианта его семантикиyuicompressor– JS/CSS minificationСтадия «produce»Генерация других файлов на основе итоговыхgzip_static– создание сжатой версии статики
Сборка пакетов – «вечная» статикаКонфигурация:<handler	name="eternal-static"process_path="/a/"target_path="/s/"match_ext="gif icojpg pngswfjscss"expand_ext="jscss"/>
Сборка пакетов – «вечная» статикаСканируем директорию process_pathна предмет статических файлов с нужными расширениямиОбрабатываем раскрываемые файлы (*.js *.css) на предмет ссылок на другие найденные ранее статические файлыСтроим граф зависимостей
Сборка пакетов – «вечная» статикаВ директории target_pathсоздаём соотв. версии статических файлов (и их gzipped-версий, если у файлов был handlergzip_static)Итоговый файл будет называтьсяfilename_revision.ext, где revision – ревизия файла/a/file.txt   /s/file_REVISION.txt
Сборка пакетов – «вечная» статикаДля статического файла, который не имеет зависимостей (в т.ч. тех, которые не раскрываются вообще, типа картинок), ревизия равна mtimeVCS ревизия может быть недоступна, если файл генерировался.При генерации файлов mtimeфинального файла всегда равен максимальному mtimeего исходных файлов
Сборка пакетов – «вечная» статикаДля статического файла, который имеет зависимости, ревизия вычисляется как md5( join('\0', mtime, sort@eternal_static_deps) ) - т.е. создаётся семантически уникальная ревизия файла.Жёсткое создание ревизии (md5 от тела файла) не используется, чтобы при изменениях контента, которые семантически инвариантны (например, применён новый алгоритм оптимизации/obfuscation файлов) не создавалась новая ревизия.
Сборка пакетов – «вечная» статикаСоздаём файл /s/.mapping, который содержит строки с парами "статический файл", "вечно-статический файл":/a/js/base.js   /s/js/base_iv6uTQ.js/s/css/main.css /s/css/main_msy5mT8H-Ak6hBAsce-30w.css
Пример: www.openstat.ru<!DOCTYPE HTML><html lang="ru"><head> <title>Интернет-статистика и веб-аналитика | Openstat: Независимая аналитика</title> <link rel="stylesheet" type="text/css" href="/s/css/main_msy5mT8H-Ak6hBAsce-30w.css" /> <script type="text/javascript" src="/s/js/base_iv6uTQ.js"></script>
Установка пакетовФайлы ставятся в share/htdocs/frontendНа этапе POST-INSTALL запускаем:rsync -rlptgoD--checksum--delete-after share/htdocs/frontendhtdocs/frontendЭто делается для того, чтобы при удалении пакета в htdocs/frontendчто-то оставалось
Установка пакетовТакже копируем вечную статику:rsync -rlptgoD--checksumhtdocs/frontend/s/htdocs/eternalВ htdocs/eternalфайлы никогда не удаляются!
Установка пакетовРаскрываем(и атомарно замещаем) файлы шаблонов по списку из /s/.mapping:htdocs/backendПоскольку директория /a/также ставится, то задержка в раскрытии файлов, равно как их нераскрытиене влияет фатально на работу сайта - просто запросы пойдут к "менее вечной" статике.
Конфигурация frontend’аПример для обычного веб-сервера:location ^~ /s/   {      alias   htdocs/eternal;gzip_static on;      expires max;}
СоглашенияСоглашения для раскрываемых файлов:Полное указание пути на ссылаемые файлыВ JS не использовать составление URLиз частей , прописывать в коде полностью(как hash)
faviconIE(и иные браузеры) всегда запрашивают /favicon.ico, если нет<link rel=”icon” …/>Выдавать 404 – не выход, поскольку запросы всё равно будут идтиПравильно так:location = /favicon.ico {root /path/to/htdocs;expires 30d;}
IV. Tips & tricks52
Битва за байты: заголовкиЗаголовок 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
Битва за байты: HTML5 vs. XHTML
Используем TLS/SSLTLS/SSL – уже не дорого в плане вычислений (CPU)Отдельные аппаратные акселераторы уже не нужныCPU Intel Core i5+ поддерживают AES instruction setPrivacy & confidentiality – всегда популярно среди параноиковhttps://gmail.com, https://encrypted.google.comЦена сертификата Thawte - всего $45
Минусы TLS/SSLДополнительные 4+ IP пакета на handshake (размер public key имеет значение!)Больший размер ответовrecord header, padding (если block cipher)При тщательно подобранном размере ответа ресурса (чтобы, скажем, влез в 1 IP пакет),применение SSL может повлечь +1 IP пакет
Минусы TLS/SSLБлокирование на OCSP (проверка сертификата сервера) = +N*100msFF3+;    IE* on Vista / Win7, …Решение - OCSP staplingНе работает с chained certs+~1KB данных (OCSP ответ)Есть в Apache, нет в nginx
Минусы TLS/SSLSSL + IE6/7+data:uriв HTML =«небезопасный ресурс»Доля IE6 + IE7 в Рунете - 9%SSL + отдача статики параллельно с нескольких хостов= дополнительные затраты на сертификатылибо несколько сертификатов для разных хостов (www.foobar.ru,     img.foobar.ru)либо условно дорогой wildcard(*.foobar.ru)
Вопросы?(по теме доклада)http://protey.ru/blog/2011/04/rit-2011.htmlСергей Скворцовskv@protey.ru59

Eternal static (RIT 2011)

  • 1.
    «Вечная статика»оптимизация отдачиконтентаСергей Скворцов2011-04-26
  • 3.
  • 4.
    Стороны и связьБраузеротображение/рендерингстраниц/данныхПротоколпередача данных: запрос-ответ или streamСерверприём запросов, формирование и передача ответов
  • 5.
    Скорость показа контентаСкорость отображенияв браузереСкорость передачи по сетиСкорость ответа от сервера
  • 6.
    1)Скорость отображения в браузереРендеринг/ вёрсткаВстраивание ресурсов/данныхData URI, CSS spritesувеличивает размер ответаAJAX, WebSocketsОтложенная загрузка;PrefetchingJavaScript: async/defer; post-load
  • 7.
    1.1) Рендеринг/вёрсткаКорректный порядок указания ресурсов (JS/CSS)Yahoo «BestPractices 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 – безопасность, но overheadSPDY – только Google, нет поддержки в nginx :)
  • 11.
    3)Скорость ответа от сервераСкорость генерации ответаУменьшениеразмера ответаУменьшение размера запросаУменьшение числа запросов
  • 12.
    3.1) Скорость генерации ответаХорошие frontend’ыБыстрыесерверы приложений (backend’ы)Прогрессивная отдача контента flush()Кэширование:данных (memcached)ответа (mod_cache*)
  • 13.
    3.2) Уменьшение размера ответаСжатие ответаngx_http_gzip, ngx_http_gzip_static mod_gzip, mod_deflateОтложенная «подгрузка» JS, контентаPost-loading
  • 14.
    3.2) Уменьшение размера ответаОптимизация содержимого (minification)Оптимизация JS/CSS Closurecompiler, YUI CompressorОптимизация графикиОптимизация HTMLПробелы, комментарии, default атрибуты, …htmlcompressor,или при компиляции шаблонов 
  • 15.
    3.3) Уменьшение размера запросаОтдача статикив другом домене Чтобы не слать лишние заголовки: CookieУменьшаем размер CookieFYI: максимальный суммарный размер на домен:Firefox, Chrome - no limitOpera, IE6 - 4096байтIE8 - 10234байт
  • 16.
    3.4) Уменьшение числа запросовКэширование контентана стороне браузераОбъединение стилей и скриптов (JS, CSS)Объединение и внедрение картинок(CSS sprites, Data URI, MHTML)ценой большего размера ответаИзбегать редиректов
  • 17.
    ИтогоВсё вышеописанное можноиспользовать как checklist, варианты ответов:Уже так делаемНе делаем, потому что (программисты|админы) сказали что…Не знали / совсем забыли – надо подумать
  • 18.
  • 19.
    Как работает кэшированиев HTTPПри первом запросе к ресурсу браузер:Запоминает заголовки ответаLast-Modified и/ли ETagОпределяет сколько времени можно не обращаться к серверу, а использовать локальный кэш - на основе данных из заголовков:ExpiresCache-Controlhttp://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-timestampIIS:Filetimestamp:ChangeNumberЭто не работает на кластере машинinodeи ChangeNumberбудут разные
  • 22.
    Проблемы этого дняЗаголовкиExpiresиCache-Control: max-age тупо не выставляют56% запросов вообще не указывают expiration24% запросов может кэшироваться 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;}
  • 28.
    ПрименимостьСтоит применять для:Файловстилей и скриптов (CSS, JS)Картинок, являющихся частью дизайна/шаблонаFlash-объектовНе надо применять для:Скачиваемых файлов (и подлежащих индексации)Особо актуально:Мобильные сайты
  • 29.
  • 30.
  • 31.
  • 32.
    HTTP Archive:медиана размераответаhttp://httparchive.org/interesting.php#responsesizes
  • 33.
  • 34.
    Htdocs layoutНа файловойсистеме:htdocs/ frontend/ eternal/ backend/frontend - статика, отдаётся nginx
  • 35.
  • 36.
    backend - шаблоны,используются в upstreamVCS layoutВ репозитории:trunk/htdocs-frontend/ a/css/img/js/htdocs-backend/
  • 37.
    Сборка пакетов: шагиCheckoutProcessingСтадия«generate»Стадия «preprocess»Стадия «optimize»Стадия «produce»Генерация «вечной статики» (кладём в /s/)Packing distfiles
  • 38.
    Сборка пакетов –ProcessingСтадия «generate»Генерация новых файлов, на основе checkout’аimg2css– набор иконок в один CSS файлСтадия «preprocess»Изменение содержимого файла, и/ли метаданных о нёмinline-includes– объединение файловCSS: раскрытие @importJavaScript: раскрытие _include_js()
  • 39.
    Сборка пакетов –ProcessingСтадия «optimize»Оптимизация формата файла, с сохранением инварианта его семантикиyuicompressor– JS/CSS minificationСтадия «produce»Генерация других файлов на основе итоговыхgzip_static– создание сжатой версии статики
  • 40.
    Сборка пакетов –«вечная» статикаКонфигурация:<handler name="eternal-static"process_path="/a/"target_path="/s/"match_ext="gif icojpg pngswfjscss"expand_ext="jscss"/>
  • 41.
    Сборка пакетов –«вечная» статикаСканируем директорию process_pathна предмет статических файлов с нужными расширениямиОбрабатываем раскрываемые файлы (*.js *.css) на предмет ссылок на другие найденные ранее статические файлыСтроим граф зависимостей
  • 42.
    Сборка пакетов –«вечная» статикаВ директории target_pathсоздаём соотв. версии статических файлов (и их gzipped-версий, если у файлов был handlergzip_static)Итоговый файл будет называтьсяfilename_revision.ext, где revision – ревизия файла/a/file.txt /s/file_REVISION.txt
  • 43.
    Сборка пакетов –«вечная» статикаДля статического файла, который не имеет зависимостей (в т.ч. тех, которые не раскрываются вообще, типа картинок), ревизия равна mtimeVCS ревизия может быть недоступна, если файл генерировался.При генерации файлов mtimeфинального файла всегда равен максимальному mtimeего исходных файлов
  • 44.
    Сборка пакетов –«вечная» статикаДля статического файла, который имеет зависимости, ревизия вычисляется как md5( join('\0', 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
  • 46.
    Пример: www.openstat.ru<!DOCTYPE HTML><htmllang="ru"><head> <title>Интернет-статистика и веб-аналитика | Openstat: Независимая аналитика</title> <link rel="stylesheet" type="text/css" href="/s/css/main_msy5mT8H-Ak6hBAsce-30w.css" /> <script type="text/javascript" src="/s/js/base_iv6uTQ.js"></script>
  • 47.
    Установка пакетовФайлы ставятсяв share/htdocs/frontendНа этапе POST-INSTALL запускаем:rsync -rlptgoD--checksum--delete-after share/htdocs/frontendhtdocs/frontendЭто делается для того, чтобы при удалении пакета в htdocs/frontendчто-то оставалось
  • 48.
    Установка пакетовТакже копируемвечную статику:rsync -rlptgoD--checksumhtdocs/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)
  • 52.
    faviconIE(и иные браузеры)всегда запрашивают /favicon.ico, если нет<link rel=”icon” …/>Выдавать 404 – не выход, поскольку запросы всё равно будут идтиПравильно так:location = /favicon.ico {root /path/to/htdocs;expires 30d;}
  • 53.
    IV. Tips &tricks52
  • 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
  • 55.
  • 56.
    Используем TLS/SSLTLS/SSL –уже не дорого в плане вычислений (CPU)Отдельные аппаратные акселераторы уже не нужныCPU Intel Core i5+ поддерживают AES instruction setPrivacy & 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*100msFF3+; IE* on Vista / Win7, …Решение - OCSP staplingНе работает с chained certs+~1KB данных (OCSP ответ)Есть в Apache, нет в nginx
  • 59.
    Минусы TLS/SSLSSL +IE6/7+data:uriв HTML =«небезопасный ресурс»Доля IE6 + IE7 в Рунете - 9%SSL + отдача статики параллельно с нескольких хостов= дополнительные затраты на сертификатылибо несколько сертификатов для разных хостов (www.foobar.ru, img.foobar.ru)либо условно дорогой wildcard(*.foobar.ru)
  • 60.