Постоянное хранилище и кэширование HTTP

внешний интерфейс HTTP JavaScript HTML

В этой статье в основном изучаются некоторые дополнительные знания HTTP, такие какSession LocalStorage Cache-Control Expires ETag

На самом деле речь идет в основномТехнология постоянного хранения и кэширования

До этого научилсяCookieизсвязанная информация,ноCookieОдним из недостатков является то, что его можно изменить искусственно, что имеет определенные риски для безопасности.

Поэтому в ответ на этот недостаток родилсяSession

Session

Вообще говоряSessionоснован на файлах cookie, он используетsessionIdЧтобы скрыть конфиденциальные пользователи данных, если не будет возможно получить конфиденциальные данные.

sessionId

Мы используемCookieКогда сервер отправляет заголовок ответа пользователю, он обычно устанавливаетCookie

response.setHeader('Set-Cookie', 'sign_in_email=...;HTTPOnly')

Поскольку сеанс по-прежнему основан наCookieреализована, то она все равно должна бытьSet-CookieСделай что-нибудь.

//预先在服务器端预留对象准备存储各种session
let sessions = {

}
...
let sessionId = Math.random() * 100000
sessions[sessionId] = {sign_in_email: email}
response.setHeader('Set-Cookie', `sessionId=${sessionId};HTTPOnly`)

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

Когда пользователь в следующий раз посетит другие страницы веб-сайта, это принесетsessionId, сервер получает этоsessionIdЗатем, как только вы конвертируете, вы знаете, что это правильный пользователь.

let sessions = {
  sessionId: {
    sign_in_email: ...
  }
}

Постоянное хранение

Внутри HTMLjs文件Переменные или объекты в нем будут умирать и восстанавливаться всякий раз, когда веб-страница обновляется, хотя она остается прежней.a, но после рефреша уже другой кусок памяти. Поскольку он не изменился, почему бы нам не сохранить его даже после обновления?aеще чтоa, что означает постоянное хранилище. использовался раньшеCookieсделать эту функцию, ноCookieКаждый раз, когда делается запрос, все в файле cookie будет отправлено на сервер, что увеличивает нагрузку на память, а время ответа на запрос велико, поэтомуhtml5дал новый APIlocalStorage

Что касается того, как работают файлы cookie, я обнаружилэта статьяочень хорошо написано

LocalStorage

по сути этоhash, но существует на стороне браузера, в отличие отsessionсуществуют на стороне сервераhash. Как правило, бесполезная или нечувствительная информация хранится.

localStorageЭто глобальное свойство окна Существует три часто используемых метода.

//1. 添加键、值
localStorage.setItem('a', '...')
//2. 获得键、值
localStorage。getItem('a')
//3.清空localStorage
localStorage.clear()

Обратите внимание, что все значения, которые он хранит, являются строками, даже если вы пишете его как объект, это бесполезно.

Если вы хотите хранить строки, вам нужно использоватьJSON.stringify( )

全是字符串

практическое применение

Очень простой пример: веб-сайт был обновлен, пользователь вошел в систему, и я хочу сообщить пользователю --- у меня есть что-то новое. Это сообщение не должно повторяться пользователю каждый раз, когда он обновляется, а только тогда, когда первый пользователь Просто скажите ему, когда войдете.

 let already = localStorage.getItem('已经提示过了')
 if (!already) {
   alert('我们的网站新进了一些货物,您看一下有没有您需要的啊O(∩_∩)O~')
   localStorage.setItem('已经提示过了', true)
 } else {

}

При первом посещении,alreadyДля нулевого, так войтиifфрагмент кода, который запрашивает пользователя один раз, а затем помещаетalreadyустановить какtrue, не войдетif, он больше не будет подсказывать.

实际应用

не основано наCookieизsession

научилсяlocalStorage, вы можете заниматься некоторыми черными технологиями, как упоминалось ранее,sessionCookieДа, а есть исключения?

немного. используя параметры запроса иlocalStorageНо реализацияsessionИдентификатор`.

Резюме

  1. Функции файлов cookie
    • Сервер передает клиенту строку через заголовок Set-Cookie.
    • Каждый раз, когда клиент посещает веб-страницу с тем же доменным именем, он должен выводить эту строку
    • Клиент хочет сохранить этот файл cookie в течение определенного периода времени.
    • По умолчанию срок действия файла cookie истекает после того, как пользователь закроет страницу, и фоновый код может произвольно установить время истечения срока действия файла cookie. Например, max-age и о чем пойдет речь далееExpires
    • Вероятно, меньше, чем размер 4kb
  2. Особенности сеанса
    • Отправьте SessionID (случайное число) клиенту через файл cookie
    • Когда клиент обращается к серверу, сервер считывает SessionID
    • На сервере есть часть памяти (хеш-таблица), в которой хранятся все сеансы.
    • Через SessionID мы можем получить личную информацию соответствующего пользователя, такую ​​как идентификатор, адрес электронной почты
    • Эта память (хеш-таблица) — это все сессии на сервере
  3. Особенности локального хранилища
    • LocalStorage не имеет ничего общего с HTTP
    • То есть отправка любого запроса не принесет значение LocalStorage
    • Только страницы с одинаковым доменным именем могут читать друг друга LocalStorage (не так строго, как одно и то же происхождение)
    • Максимальная емкость хранилища localStorage для каждого доменного имени составляет около 5 МБ (разная для каждого браузера).
    • Общие сценарии: запишите, был ли запрос пользователю (бесполезная информация, не может записывать конфиденциальную информацию, такую ​​​​как пароли)
    • LocalStorage является постоянным, если пользователь не очистит кеш

清理缓存

SessionStorage

Основные возможности хранения сессий иlocalStorageПо сути то же самое, самая большая разницаSessionStorageСбой в работе пользователя закрывает страницу (сеанс завершается) после.

Предположим, что файл, к которому мы хотим получить доступ, относительно большой. После того, как мы его запросим, ​​загрузка займет много времени. Когда мы обновляем страницу, хотя файл не обновляется, мы снова загружаем большой файл с сервера, в результате чего каждый Время отклика по-прежнему очень долгое.

加载时间很长

Из приведенного выше эксперимента видно, чтоlocalhostОтвет на запрос очень быстрый, 10 мс;default.css,main.jsФайл больше и время откликаlocalhost25 раз,jqИспользуемый файлcdnУскорение, получаемое от кеша в памяти, почти мгновенное. Если это происходит каждый раз, пользовательский опыт должен быть плохим.


Так можно не идти на сервер скачивать, если ресурс не обновится после первого ответа, а где-то взять?

Ответ положительный, этого можно добиться с помощью кэширования, как показано на рисунке выше.jqСпособ достижения тот же.

Эту часть можно использовать как метод оптимизации веб-производительности.

Cache-Control

пройти черезmax-ageУстановите действительное время (длительность) кеша

 if (path === '/css/default.css'){
    let string = fs.readFileSync('./css/default.css', 'utf8')
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.setHeader('Cache-Control', 'max-age=1000000')
    response.write(string)
    response.end()
  }

добавить в заголовок ответаCache-Control, указывающее, что в течение 100 000 секунд не обращаться к серверу за этим ресурсом, а просто получить его из моего кеша памяти.

缓存的技术

多次刷新后

Несмотря на то, что используется технология кэширования, есть небольшие сомнения, что иногда она получается из кэша жесткого диска.Это улучшение скорости невелико, но все же позволяет избежать процесса повторного запроса сервера для получения ресурсов; иногда это полученный из кеша памяти. , это очень быстро. Наверное потому что кеш памяти очень быстрый.

Обычно мы ставимCache-ControlЭффективное время установлено очень долго.

Возьмем, к примеру, частые посещения Huobi.

Если файл долгое время остается неизменным, установите его получение из кеша. Zhihu установил эффективное время 32596169 секунд, что превышает время 1 год = 31536000 секунд.

Старайтесь не использовать технологию кэширования на главной странице

Мы просматриваем некоторые веб-сайты на основе форумов или новостей, уделяем внимание своевременности и, как правило, размещаем взрывной высококачественный контент на главной странице. Я установил кеш, но все еще вижу домашнюю страницу 10 минут назад, которая стыдно☺…

Поэтому старайтесь не использовать технологию кеширования на главной странице, а применяйте технологию кеширования только для тех файлов и картинок, которые долгое время остаются неизменными.

Возьмем, к примеру, Чжиху.

以知乎为例

Для ЧжихуCache-ControlЯ более смущен.

Синтаксис MDNначальство

  1. public

Indicates that the response may be cached by any cache.

  1. private

Indicates that the response is intended for a single user and must not be stored by a shared cache. A private cache may store the response.

  1. no-cache

Forces caches to submit the request to the origin server for validation before releasing a cached copy.

  1. no-store

The cache should not store anything about the client request or server response.

  1. must-revalidate

The cache must verify the status of the stale resources before using it and expired ones should not be used.

MDN рекомендует закрывать кеш следующим образом:Cache-Control: no-cache, no-store, must-revalidate.

Итак, если некоторые ресурсы действительно обновляются, как обновить кеш.

обновить кеш

через серверный кодserver.jsмы можем узнать, что

if (path === '/js/main.js') {
  ...
  response.setHeader('Cache-Control', 'max-age=1000000')
  ...
} else if (path === '/css/default.css'){
  ...
  response.setHeader('Cache-Control', 'max-age=1000000')
  ...
}

покаURLПри выполнении требований будет использована технология кэширования, и ресурс не будет повторно загружен без инициирования запроса.

Итак, когда файл действительно обновлен, мы можем изменитьURL, то он повторно загрузит новый файл.

Поскольку наша веб-записьhtmlВы можете быть там руками и ногами

...
<script src="./js/main.js?V2"></script>
...

После того, как вы обновите код, теоретически вам нужно будет только добавить параметры запроса к URL-адресу.?V2Вот и все.


Давайте отправимся в Zhihu, чтобы увидеть их примеры.

更新缓存

Видно, что Чжиху тоже ставитURLЭто было изменено, но это более продвинуто, чем мой. Он руководил именем файла, вероятно, в каком использованном каркасном или обработке инструмент, но идея обновления кэша одинакова. Изменения файла, чжиху кэширует файлURLЗалить что-то; не менял, потом кеширует год, в винчестере где-то спать ^_^ года.

Резюме

Используйте кэш для использованияresponse.setHeader('Cache-Control', 'max-age=100000'), когда вы хотите обновить, измените файлURL.

缓存技术

Конечно, если кешей слишком много, ваш жесткий диск, по оценкам, взорвется.Браузер будет взвешивать их, и должно быть ясно, какие кеши должны быть приоритетными, что является делом браузера.

Как говорится, не забывайте копать, когда вы едите колодец, вы должны научиться помнить трудное и думать о сладком, мы сейчас используем прохладные.Cache-ControlОн не возник из ниоткуда, на это есть исторические причины, в прошлом его использовали дляExpiresМетоды реализации кэширования.

Expires

ExpiresАнглийский означает зрелость, он явно связан с технологией кэширования, но вы также можете видеть, что его английское значение в какой-то степени не соответствует смыслу, а неCache-ControlЭффективное время.

MDN的语法

Как видно из синтаксиса и примеров, он основан на GMT.

мы должны иметь дело со временем

var d = new Date() //Sat Feb 10 2018 11:18:54 GMT+0800 (CST)
d.toGMTString() //"Sat, 10 Feb 2018 03:18:54 GMT"

Видно, что самым большим недостатком этого заголовка ответа является то, чтоВременные метки связаны с вашим местным временем

Если система времени локального компьютера сбита с толку, а такого рода баги действительно случаются время от времени, то ваш кеш бесполезен. Возможно, именно поэтому HTTP необходимо обновить этот заголовок ответа O(∩_∩)O~

когдаCache-Controlа такжеExpiresпри сосуществовании

Если есть другой набор директив "max-age" или "s-max-age"Cache-Controlзаголовок ответа, затемExpiresзаголовки игнорируются.

По технологии кэширования есть последний братETagПрежде чем исправить это, давайте узнаем о его помощникеMD5

MD5

MD5является алгоритмом дайджеста. Часто используется для сравнения двух одинаковых файлов. Если есть небольшая разница, ошибка будет усиливаться. Например, если мы часто переустанавливаем систему, добросовестный системный провайдер даст вам соответствующуюMD5значение, после загрузки проверьте, совпадает ли значение MD5 загруженной вами системы с официально предоставленным вам, и убедитесь, что загруженная вами вещь не является неполной из-за сетевых причин.

существуетLinuxиспользуется в системеmd5sumИнструкция выполняет проверку MD5

MD5校验

Внутри первой красной коробки находится1.txtФайл (контент устанавливается на 123456) значение MD5, которое является второй красной коробкой1-copyФайл (я изменил содержимое на 123 460) Значение MD5.

существуетnodejsКак его использовать в нем, гугл нашел, что естьnpmизMD5.

npm install md5
...
//在server.js引入
var md5 = require('md5');

Подготовительная работа сделана, вы можете сделать этоETag.

ETag

The ETag HTTP response header is an identifier for a specific version of a resource.It allows caches to be more efficient, and saves bandwidth, as a web server does not need to send a full response if the content has not changed. On the other side, if the content has changed, etags are useful to help prevent simultaneous updates of a resource from overwriting each other ("mid-air collisions").

If the resource at a given URL changes, a new Etag value must be generated. Etags are therefore similar to fingerprints and might also be used for tracking purposes by some servers. A comparison of them allows to quickly determine whether two representations of a resource are the same, but they might also be set to persist indefinitely by a tracking server.

  • Этот заголовок ответа является идентификатором конкретной версии ресурса.
  • Если ресурс в данном URL-адресе изменится, обязательно сгенерируйте новое значение Etag. Таким образом, Etags подобны отпечаткам пальцев и также могут использоваться для отслеживания некоторыми серверами. Сравнение etags может быстро определить, изменился ли этот ресурс, но также может постоянно сохраняться сервером отслеживания.

Как можно заметитьETagЭто должна быть строка значений, на данный момент предыдущий разделMD5Это удобно, мы используем MD5 для сравнения содержимого двух файлов запроса до и после.

Когда URL-адрес обращается к ресурсам сервера, если сервер устанавливает заголовок ответаETag:一串md5值,Так

设置响应头

Нет никаких других изменений сейчас, если вы обновляете во второй раз, вы найдете

请求头变了

Еще один заголовок запросаIf-None-Match:一串MD5值.

Сравнивая две приведенные выше фотографии, мойmain.jsне изменилось, нашелETag:一串md5值а такжеIf-None-Match:一串MD5值Если вы немного подумаете об этом, вы можете понять, что если мойmain.jsИзменил, то

MD5变了

При втором запросе на сервер загруженныйmain.jsизETagЗначение MD5 должно быть другим.

В соответствии с этим явлением, затем в сочетании с документом MDN

Другим типичным вариантом использования заголовков ETag является кэширование неизмененных ресурсов. Если пользователь снова посещает данный URL-адрес (с полем ETag), это показывает, что срок действия ресурса истек и недоступен, клиент отправляет значение ETagIf-None -Match

If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

Client Server Etag (отправляется в виде значений, если - None-match Double вместе) по сравнению с их текущей версией Etag Resource, если два значения совпадают (то есть ресурс не изменен), сервер возвращает контент без каких-либо304Неизмененное состояние, сообщающее клиентам, что кэшированная версия доступна (свежая).

Можно вывести следующий код:

if (path === '/js/main.js') {
    let string = fs.readFileSync('./js/main.js', 'utf8')
    response.setHeader('Content-Type', 'application/javascript;charset=utf-8')
    let fileMd5 = md5(string)
    response.setHeader('ETag', fileMd5)
    if (request.headers['if-none-match'] === fileMd5) {
      response.statusCode = 304
    } else {
      response.write(string) 
    }
    response.end()
 }

Значение кода состояния 304

HTTP 304Не нужно лишний раз объяснять запрос на передачу контента, а значит можно использовать кешированный контент. Обычно это какие-то методы безопасности (safe),НапримерGETилиHEADили с заголовками, включенными в запрос:If-None-MatchилиIf-Modified-Since.

Разница между 304 и кешем:

  1. Кэш не будет инициировать запрос, он будет получен непосредственно из памяти или жесткого диска
  2. 304 все равно начнут запрос и ответ, но четвертая часть ответа не должна быть загружена снова, потому что нет никаких изменений, поэтому он все еще является первым загруженным ресурсом.

304与缓存的区别

Некоторые распространенные экзаменационные вопросы

Разница между куки и сессиями

  1. Файлы cookie — это данные, которые хранятся на стороне браузера и отправляются на сервер с каждым запросом. место храненияcookieэто функция, предоставляемая браузером.cookieПо сути, это обычный текст, хранящийся в браузере, в каталоге установки браузера будет специальная папка cookie для хранения настроек под каждым доменом.cookie.
  2. Сессия хранится в памяти сервера, а ее идентификатор сессии отправляется клиенту через файл cookie.Этот идентификатор сеанса отправляется на сервер с каждым запросом.

Разница между файлами cookie и локальным хранилищем

  1. Set-CookieПосле этого каждый раз, когда пользователь обращается к серверу, запрос будет выполнятьсяCookieна сервер, который связан с HTTP, в то время какLocalStorageЕго не нужно отправлять на сервер, он хранится в браузере и не имеет ничего общего с HTTP, это свойство браузера.window.localStorage.
  2. CookieКак правило, небольшой, около 4k, иLocalStorageОколо 5 м можно использовать
  3. CookieПо умолчанию произойдет сбой после того, как пользователь закроет страницу, но задняя часть может установить время сохранения иLocalStorageПостоянный, если только пользователь не очистит его вручную.

Разница между LocalStorage и SessionStorage

  1. LocalStorageДействует постоянно, если пользователь не очистил его вручнуюlocalStorage.clear(). Не истекает автоматически
  2. Однако SessionStorage станет недействительным после завершения сеанса, то есть пользователь закроет страницу, и она станет недействительной. истечет автоматически

Как установить срок действия файлов cookie? Как удалить куки?

  1. Установить время истечения:Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>

    data` - это среднее время по Гринвичу, код должен быть написан в заголовке ответа следующим образом

    response.setHeader('Expires', 'Fri, 09 Feb 2018 11:29:48 GMT')
    

    То есть срок действия файла cookie истекает в 11:29:48 по Гринвичу 9 февраля 2018 года.

  2. Установите срок действия файла cookie меньше текущего времени, тогда файл cookie будет удален.

function deleteCookie(name) {
  document.cookie = name + '=;  expires=Thu, 01 Jan 1970 00:00:01 GMT;'
}

Cache-Control: max-age=1000 В чем разница между кешем и кешем ETag?

  1. Cache-Control: max-age=1000Кэш не отправляет запросы напрямую, когда пользователи с одним и тем же URL запрашивают ресурсы в течение 1000 секунд, они больше не будут отправлять запросы на доступ к серверу, а будут получены непосредственно из кеша локальной памяти.
  2. ETagКэш - это инициировать запрос, несмотря ни на что, и будет дополнительный заголовок запроса, когда второй доступ сделан.If-None-Match : md5值, если значение MD5 между двумя запросами одинаково, новый файл загружаться не будет, а тело ответа загружается впервые; если значение MD5 изменилось, будет загружен новый файл.