- Русские Блоги
- Руководство по использованию кеша OkHttp
- HTTP-кеш
- Набор инструкций запроса (значение в сообщении запроса):
- Набор команд ответа (значение в ответном сообщении):
- OkHttp перехватчик
- Использовать кеш OkHttp
- Не использовать кеш OkHttp
- Кастомный перехватчик
- Отслеживайте процесс запроса OkHttp
- Сравнение достоинств и недостатков
- быть осторожен
- HTTP-кеширование
- Различные виды кеширования
- Приватный (private) кеш браузера
- Общий (shared) прокси-кеш
- Цели кеширования
- Управление кеш ированием
- Заголовок Cache-control
- Полное отсутствие кеширования
- Кешировать, но проверять актуальность
- Приватные (private) и общие (public) кеши
- Срок действия (Expiration)
- Проверка актуальности
- Заголовок Pragma
- Свежесть сохранённой копии
- Обновление статических ресурсов (Revved resources)
- Валидация кеша
- Заголовки ETag
- Изменяющиеся ответы
Русские Блоги
Руководство по использованию кеша OkHttp
HTTP-кеш
В протоколе Http управление кешем контролируется параметром Cache-Control в заголовке. Установив параметр Cache-Control, можно реализовать различные стратегии кэширования.
Cache-Control, как и другие поля заголовка, использует структуру ключ: значение, и значение может иметь несколько значений, и значения разделяются символом (см.HTTP подробно). Cache-Control — это поле общего заголовка, которое можно использовать в сообщениях HTTP-запросов, а также в ответных сообщениях.
Набор инструкций запроса (значение в сообщении запроса):
- no-cache: не кэшировать данные, получать данные напрямую с исходного сервера;
- no-store: не кэшировать содержимое запроса или ответа;
- max-age: указывает, что кэшированные данные, срок действия которых истек слишком долго, могут быть приняты, что аналогично max-stale с указанным параметром;
- max-stale: указывает на получение кэша с истекшим сроком действия. Если позже не указан параметр, это означает, что кэшированные данные принимаются всегда. Например, max-stale: 3600, что означает, что данные в течение 1 часа после истечения срока допустимы;
- min-fresh: указывает, что кэшированные данные в течение указанного времени все еще действительны, независимо от того, истек ли срок действия кеша. Например, min-fresh: 60 означает, что кэшированные данные в течение 60 секунд действительны, а кэшированные данные после 60 секунд будут недействительными.
- only-if-cache: указывает на получение кэшированных данных напрямую, если данные не возвращаются, возвращается 504 (таймаут шлюза)
Набор команд ответа (значение в ответном сообщении):
общедоступный: может предоставить кэшированные данные любой стороне;
частный: предоставлять кэшированные данные только определенным пользователям;
no-cache: подтвердите его действительность перед кешированием;
no-store: не кэшировать содержимое запроса или ответа;
max-age: указывает максимальное время кеширования в пределах этого временного диапазона, при обращении к ресурсу непосредственно возвращаются кэшированные данные. Нет необходимости подтверждать валидность ресурсов;
must-revalidate: при доступе к кэшированным данным вам необходимо подтвердить исходному серверу, действительны ли кэшированные данные.Если достоверность не может быть проверена, вам необходимо вернуть 504. Следует отметить, что при использовании этого значения max-stale будет недопустимым.
Для получения более подробной информации, пожалуйста, обратитесь к:Определение поля заголовка HTTP
Поняв теоретические знания HTTP, мы кратко представим кеш в OkHttp позже.
OkHttp перехватчик
OkHttp поддерживает кеширование Http по умолчанию.Пока ответ, возвращаемый сервером, содержит стратегию кэширования, OkHttp будет кэшировать его через перехватчик CacheInterceptor. Но OkHttp не добавляет Cache-Control к HTTP-запросу, созданному по умолчанию.Даже если сервер поддерживает его, мы все равно не можем нормально использовать кешированные данные. Поэтому нам нужно вмешаться в процесс кеширования OkHttp, чтобы он соответствовал нашим потребностям.
Элегантность OkHttp заключается в использовании модели цепочки ответственности, которая реализует каждый шаг в процессе запрос-ответ через перехватчик и предоставляет расширения для головы и хвоста процесса, что также позволяет нам вмешиваться в кеш. Процесс предоставляет возможность. Поэтому перед реализацией кеширования нам нужно иметь общее представление об обработке перехватчиков OkHttp.
Приведенный выше код представляет собой процесс обработки всего перехватчика. Конкретный процесс может относиться к исходному коду. Здесь мы говорим только о базовом процессе: когда запрос инициируется, он будет выполняться в порядке, добавленном в перехватчиках, и в обратном порядке, когда возвращается ответ:
Среди них CallServerInterceptor — это перехватчик, отвечающий за отправку запросов и получение ответов. Поскольку нас интересует только кеширование, мы рассматриваем только CacheInterceptor во встроенном перехватчике. Тогда процесс можно упростить до:
Из этого процесса видно, что если в ответе, возвращаемом сервером, нет Cache-Control, то мы можем реализовать его, добавив сетевой перехватчик. Точно так же при доступе к кэшированным данным мы можем добиться этого, добавив собственный перехватчик.
Использовать кеш OkHttp
Прежде чем мы начнем добавлять стратегию кэширования, давайте сначала разберемся с полной стратегией кэширования:
Вообще говоря, когда есть сеть, использование кеширования еще более усложняется. Здесь мы принимаем упрощенную версию стратегии кэширования (Посещать сервер при наличии сети и возвращать кэшированные данные при отсутствии сети) Чтобы продемонстрировать, как OkHttp использует кеширование.
Во-первых, мы добавляем стратегию кеширования в Response, определяя сетевой перехватчик:
Во-вторых, используйте собственный перехватчик для установки стратегии кэширования запросов:
Pragma — это поле, оставшееся от предыдущей версии Http / 1.1. Оно используется для совместимости версий, но разные платформы имеют разные реализации этого. Поэтому его необходимо экранировать при использовании стратегии кеширования, чтобы не повлиять на стратегию кеширования.
Примените перехватчик, изменяющий стратегию кэширования запросов и ответов, к OkHttp:
Тогда вы сможете без проблем использовать кэшированные данные без сети.
Не использовать кеш OkHttp
Что делать, если вы считаете, что кэширование OkHttp слишком сложно, и хотите кэшировать данные самостоятельно? Есть два варианта достижения:
- Пользовательский перехватчик,
- Наблюдать за процессом запроса OkHttp и кэшировать данные по завершении запроса;
Кастомный перехватчик
В этом решении сначала необходимо решить, использовать ли обычный перехватчик или сетевой перехватчик. Мы уже поняли порядок выполнения перехватчика во всем процессе запроса. Следует отметить, что: при отсутствии сети запрос выполняется к CacheIntercepter, Если кэшированных данных нет, они будут возвращены напрямую и не будут выполняться в настраиваемом сетевом перехватчике, поэтому кэширование данных в сетевом перехватчике не подходит. Затем мы можем реализовать это, настроив общий перехватчик. Базовый процесс выглядит следующим образом:
Отслеживайте процесс запроса OkHttp
OkHttp: У тебя совесть не задела этим решением?
Можно сказать, что это решение отказывается от мощной функции перехватчика расширения OkHttp и напрямую взаимодействует с запросами и ответами.Основной процесс выглядит следующим образом:
Сравнение достоинств и недостатков
Оба этих решения отказываются от стратегии кэширования, реализованной самим OkHttp, поэтому они более гибкие, особенно метод мониторинга процесса запроса OkHttp. Но есть и большой недостаток: необходимость реализации модуля кеширования. Конкретная стратегия кэширования, используемая при разработке, может быть измерена в соответствии с существующими модулями кода и требованиями.
быть осторожен
Перехватчик, который изменяет стратегию кэширования ответа, должен быть применен к сетевому перехватчику, в противном случае данные не могут быть кэшированы, потому что во время процесса возврата ответа обычный перехватчик выполняется после встроенного CacheInterceptor;
При изменении Cache-Control of Response max-Age не должен быть слишком большим, в противном случае вы всегда будете получать доступ к кешированным данным в течение указанного max-Age времени (даже если есть сеть);
В процессе разработки мы добавим некоторые общедоступные параметры к сетевому запросу. Для некоторых переменных общедоступных параметров их необходимо удалить в процессе кэширования данных и доступа к кэшированным данным, например, тип сети. Когда есть сеть, ее значение — Wifi или 4G и т. Д., При отсутствии сети он может отсутствовать, тогда доступ к кешу будет невозможен из-за несогласованности URL-адресов.
Источник
HTTP-кеширование
Производительность веб-сайтов и приложений можно значительно повысить за счёт повторного использования ранее полученных ресурсов. Веб-кеши сокращают задержку и снижают сетевой трафик, уменьшая тем самым время, необходимое для отображения ресурсов. Используя HTTP-кеширование, сайты становятся более отзывчивыми.
Различные виды кеширования
Техника кеширования заключается в сохранении копии полученного ресурса для возврата этой копии в ответ на дальнейшие запросы. Запрос на ресурс, уже имеющийся в веб-кеше, перехватывается, и вместо обращения к исходному серверу выполняется загрузка копии из кеша. Таким образом снижается нагрузка на сервер, которому не приходится самому обслуживать всех клиентов, и повышается производительность — кеш ближе к клиенту и ресурс передаётся быстрее. Кеширование является основным источником повышения производительности веб-сайтов. Однако, кеш надо правильно сконфигурировать: ресурсы редко остаются неизменными, так что копию требуется хранить только до того момента, как ресурс изменился, но не дольше.
Существует несколько видов кешей, которые можно разделить на две основные категории: приватные кеши и кеши совместного использования. В кешах совместного использования (shared cache) хранятся копии, которые могут направляться разным пользователям. Приватный кеш (private cache) предназначен для отдельного пользователя. Здесь будет говориться в основном о кешах браузеров и прокси, но существуют также кеши шлюзов, CDN, реверсные прокси кеши и балансировщики нагрузки, разворачиваемые на серверах для повышения надёжности, производительности и масштабируемости веб-сайтов и веб-приложений.
Приватный (private) кеш браузера
Приватный кеш предназначен для отдельного пользователя. Вы, возможно, уже видели параметры кеширования в настройках своего браузера. Кеш браузера содержит все документы, загруженные пользователем по HTTP. Он используется для доступа к ранее загруженным страницам при навигации назад/вперёд, позволяет сохранять страницы, или просматривать их код, не обращаясь лишний раз к серверу. Кроме того, кеш полезен при отключении от сети.
Общий (shared) прокси-кеш
Кеш совместного использования — это кеш, который сохраняет ответы, чтобы их потом могли использовать разные пользователи. Например, в локальной сети вашего провайдера или компании, может быть установлен прокси, обслуживающий множество пользователей, чтобы можно было повторно использовать популярные ресурсы, сокращая тем самым сетевой трафик и время ожидания.
Цели кеширования
Кеширование в HTTP не является обязательным, однако в большинстве случаев бывает полезно повторно использовать ранее сохранённые ресурсы. Тем не менее, стандартные кеши HTTP обычно способны кешировать только ответы на запросы методом GET , а другие отклоняют.
Первичный ключ состоит из метода запроса и запрашиваемого URI (зачастую используется только URI, поскольку целью кеширования являются только GET-запросы). Вот примеры того, что обычно записывается в кеш:
- Успешно загруженные ресурсы: ответ 200 OK на запрос методом GET HTML-документов, изображений или файлов.
- Постоянные перенаправления: ответ 301 Moved Permanently («перемещено навсегда»).
- Сообщения об ошибках: ответ 404 Not Found («не найдено»).
- Неполные результаты: ответ 206 Partial Content («частичное содержимое»).
Ответы на запросы отличные от GET , если есть что-либо, подходящее для использования в качестве ключа кеша.
Запись в кеше может также состоять из множества ответов, различаемых по вторичному ключу, если при формировании ответа производится согласование данных. Подробнее об этом рассказано ниже, в разделе, посвящённом заголовку Vary .
Управление кеш ированием
Заголовок Cache-control
Поле Cache-Control общего заголовка HTTP/1.1 используется для задания инструкций по механизму кеширования как в запросах, так и в ответах. Применяется для задания политик кеширования.
Полное отсутствие кеширования
В кеше не должно сохраняться ничего — ни по запросам клиента, ни по ответам сервера. Запрос всегда отправляется на сервер, ответ всегда загружается полностью.
Кешировать, но проверять актуальность
Перед тем, как выдать копию, кеш запрашивает исходный сервер на предмет актуальности ресурса.
Приватные (private) и общие (public) кеши
Директива «public» указывает, что ответ можно сохранять в любом кеше. Это бывает полезно, если возникает потребность сохранить страницы с HTTP-аутентификацией, или такими кодами ответа, которые обычно не кешируются. Директива же «private» указывает, что ответ предназначен отдельному пользователю и не должен храниться в кеше совместного использования. В этом случае ответ может сохраняться приватным кешем браузера.
Срок действия (Expiration)
Самой важной здесь является директива «max-age= » — максимальное время, в течение которого ресурс считается «свежим». В отличие от директивы Expires , она привязана к моменту запроса. К неизменяющимся файлам приложения обычно можно применять «агрессивное» кеширование. Примером таких статических файлов могут быть изображения, файлы стилей (CSS) или скриптов (JavaScript).
Подробнее об этом рассказывается в разделе Свежесть ресурса.
Проверка актуальности
При использовании директивы «must-revalidate» кеш обязан проверять статус ресурсов с истёкшим сроком действия. Те копии, что утратили актуальность, использоваться не должны. Подробнее об этом рассказано ниже, в разделе Валидация кеша.
Заголовок Pragma
Pragma является заголовком HTTP/1.0. Он не описан для HTTP-ответов и, таким образом, не может служить надёжной заменой общему заголовку Cache-Control протокола HTTP/1.1, хотя его поведение аналогично «Cache-Control: no-cache» когда поле заголовка Cache-Control опущено в запросе. Использовать его следует только для совместимости с клиентами HTTP/1.0.
Свежесть сохранённой копии
Однажды попав в кеш, ресурс, теоретически, может храниться там вечно. Однако, поскольку объем хранилища конечен, записи периодически приходится оттуда удалять. Этот процесс называют вытеснением данных из кеша (cache eviction). Кроме того, ресурсы могут изменяться на сервере, поэтому кеш требуется обновлять. Поскольку HTTP является клиент-серверным протоколом, сервера не могут сами обращаться к кешам и клиентам при изменении ресурса; им необходимо договориться о сроке действия сохранённой копии. До его истечения ресурс считается свежим (fresh), после — устаревшим (stale). Алгоритмы вытеснения отдают предпочтение «свежим» ресурсам. Тем не менее, копия ресурса не удаляется из кеша сразу же по истечении её срока действия; при получении запроса на устаревший ресурс кеш передаёт его дальше с заголовком If-None-Match (en-US) на случай, если копия все ещё актуальна. Если это так, сервер возвращает заголовок 304 Not Modified («не изменялось»), а тело ресурса не посылает, экономя тем самым трафик.
Вот пример того, как протекает этот процесс при использовании совместного кеша прокси:
Срок действия (freshnessLifetime) вычисляется на основании нескольких заголовков. Если задан заголовок «Cache-control: max-age=N», то срок действия равен N. Если его нет, а это бывает очень часто, проверяется заголовок Expires , и, если он есть, то срок действия берётся равным значению заголовка Expires минус значение заголовка Date. Наконец, если нет ни того ни другого, смотрят заголовок Last-Modified. Если он есть, то срок действия равен значению заголовка Date минус значение заголовка Last-modified разделить на 10.
Время устаревания (expirationTime) вычисляется следующим образом:
где responseTime — это время получения ответа по часам браузера, а currentAge — текущий возраст кеша.
Обновление статических ресурсов (Revved resources)
Чем больше ресурсов может быть взято из кеша, тем быстрее сайт реагирует на запросы и тем выше его производительность. Из этих соображений их «срок годности» имеет смысл делать как можно большим. Однако, возникает проблема с ресурсами, которые обновляются редко и нерегулярно. Как раз их кеширование даёт больше всего выгоды, но сильно затрудняет обновление. Такие ресурсы можно найти на любой веб-странице: файлы скриптов (JavaScript) и стилей (CSS) изменяются редко, но уж если это произошло, обновление надо произвести как можно быстрее.
Веб-разработчики разработали метод, который Стив Сандерс (Steve Sounders) назвал revving [1] , что можно перевести как «оборачиваемость». Для редко обновляемых файлов используют особый способ именования: в их URL, обычно в имя файла, добавляют номер релиза или версии. Таким образом, каждая новая версия считается отдельным ресурсом, срок устаревания которого отодвинут далеко в будущее, как правило, на год, или больше. Недостатком этого метода является то, что для получения новых версий ресурса приходится обновлять все ссылки на него — это некоторое усложнение, справиться с которым разработчику помогает цепочка инструментов. Обновление статических ресурсов влечёт за собой обновление и часто изменяемых ресурсов. Когда считываются первые, считываются и новые версии вторых.
Этот метод имеет дополнительное достоинство: одновременное обновление двух кешированных ресурсов не приводит к ситуации, при которой устаревшая версия одного ресурса используется вместе с новой версией другого. Это очень важно для сайтов с взаимосвязанными файлами стилей CSS или JS-скриптов — связь может возникнуть, например, из-за ссылок на одни и те же элементы HTML-страницы.
Номер версии, добавляемый к статическому ресурсу, не обязательно записывать в виде стандартного номера версии наподобие 1.1.3, или другого возрастающего числового значения. Это может быть что угодно, позволяющее избежать совпадений — например, дата.
Валидация кеша
Валидация кеша запускается при нажатии пользователем кнопки перезагрузки. Кроме того, она может выполняться в ходе обычного просмотра страниц, если кешированный ответ включает заголовок «Cache-control: must-revalidate». Другим фактором являются настройки кеширования браузера — можно потребовать принудительной валидации при каждой загрузке документа.
При истечении срока годности документа он либо проходит валидацию, либо повторно доставляется с сервера. Валидация может выполняться только если на сервере реализован сильный валидатор или слабый валидатор.
Заголовки ETag
Заголовок ответа ETag является непрозрачным для клиентского приложения (агента) значением, которое можно использовать в качестве сильного валидатора. Суть в том, что клиент, например, браузер, не знает, что представляет эта строка и не может предсказать, каким будет её значение. Если в ответе присутствует заголовок ETag , клиент может транслировать его значение через заголовок If-None-Match (en-US) будущих запросов для валидации кешированного ресурса.
Заголовок ответа Last-Modified можно использовать в качестве слабого валидатора. Слабым он считается из-за того, что имеет 1-секундное разрешение. Если в ответе присутствует заголовок Last-Modified , то для валидации кешированного документа клиент может выводить в запросах заголовок If-Modified-Since .
При запросе на валидацию сервер может либо проигнорировать валидацию и послать стандартный ответ 200 OK , либо вернуть ответ 304 Not Modified (с пустым телом), тем самым указывая браузеру взять копию из кеша. В последнем случае в ответ могут входить также заголовки для обновления срока действия кешированного ресурса.
Изменяющиеся ответы
Заголовок HTTP-ответа Vary определяет, как по заголовкам будущих запросов понять, может ли быть использована копия из кеша, или нужно запросить новые данные у сервера.
Если кеш получает запрос, который можно удовлетворить сохранённым в кеше ответом с заголовком Vary , то использовать этот ответ можно только при совпадении всех указанных в Vary полей заголовка исходного (сохранённого в кеше) запроса и нового запроса.
Это может быть полезно, например, при динамическом предоставлении контента. При использовании заголовка Vary: User-Agent кеширующие сервера, принимая решение об использовании страницы из кеша, должны учитывать агент пользователя. Так можно избежать ситуации, когда пользователи мобильных устройств по ошибке получат десктопную версию вашего сайта. Вдобавок, это может помочь Google и другим поисковым системам обнаружить мобильную версию страницы, и может также указать им на то, что здесь нет никакой подмены контента с целью поисковой оптимизации (Cloaking).
Поскольку значение заголовка User-Agent (en-US) различается («varies») у мобильных и десктопных клиентов, закешированный мобильный контент не будет по ошибке отсылаться пользователям десктопов и наоборот.
Источник