читать оригинал
предисловие
Являясь важным средством оптимизации производительности веб-приложений, механизм HTTP-кэширования должен быть основным звеном системы знаний для студентов, занимающихся веб-разработкой, а также необходимым навыком, чтобы стать фронтенд-архитектурой.
Роль кэширования
Почему мы используем кэширование, так это потому, что кэширование может дать нашим веб-проектам следующие преимущества для повышения производительности и взаимодействия с пользователем.
- Ускорить браузерную загрузку веб-страниц;
- Уменьшите избыточную передачу данных, сэкономьте сетевой трафик и пропускную способность;
- Снизьте нагрузку на сервер и значительно повысьте производительность сайта.
Поскольку статические ресурсы считываются из локального кеша, это, безусловно, ускорит скорость загрузки веб-страницы браузера, а также уменьшит передачу данных.Что касается повышения производительности веб-сайта, одно или два посещения пользователя не может значительно снизить нагрузку на сервер Эффективно, но если веб-сайт находится в режиме высокой параллелизма, использование кеша приведет к качественному изменению в снижении нагрузки на сервер и производительности всего веб-сайта.
Введение в правила кэширования
Для облегчения понимания мы думаем, что у браузера есть кеш-база данных для хранения информации о кеше (на самом деле статические ресурсы кешируются в памяти и на диске). данных кеша, вам нужно запросить сервер, сервер вернет правила кеша и данные, а браузер сохранит правила кеша и данные в базе данных кеша.
Запрашивается при вводе адреса в адресной строке браузераindex.html
не кэшируется, аindex.html
Другие ресурсы, запрашиваемые внутри, будут следовать стратегии кэширования.Существуют различные правила кэширования HTTP, которые в основном делятся на две категории в зависимости от необходимости отправки запроса на сервер, принудительного кэширования и согласованного кэширования.
Принудительно кэшировать
1, процесс принудительного кэширования
Принудительное кэширование означает, что после первого обращения к серверу для получения данных сервер не будет повторно запрашиваться в течение допустимого времени, а кэшированные данные будут использоваться напрямую.Процесс принудительного кэширования выглядит следующим образом.
2. Заставить кеш определить время истечения срока действия
Итак, как определить, истек ли срок действия кеша? На самом деле он по-прежнему реализуется в соответствии с заголовком ответа сервера при первом обращении к нему.HTTP 1.0
версия иHTTP 1.1
Версии различаются.
существуетHTTP 1.0
версия, поле заголовка ответа, используемое сервером,Expires
, значение представляет собой абсолютное время (отметку времени) в будущем, текущее время на момент запроса браузера превышаетExpires
Установленное время указывает на то, что кеш недействителен, и запрос нужно отправить на сервер повторно, иначе данные будут получены непосредственно из базы данных кеша.
существуетHTTP 1.1
версия, поле заголовка ответа, используемое сервером,Cache-Control
, имеет несколько значений с разными значениями.
- частный: клиент может кэшировать;
- общедоступный: и клиент, и прокси-сервер могут кэшировать (для внешнего интерфейса это можно считать тем же, что и
private
тот же эффект); - max-age=xxx: кэшированное содержимое будет
xxx
Истекает в секундах (относительное время в секундах); - без кеша: согласованный кеш (описанный ниже) требуется для проверки того, не просрочены ли данные;
- no-store: весь контент не будет кэшироваться, ни принудительный кеш, ни согласованный кеш не сработают.
Cache-Control
Наиболее часто используемые значенияmax-age=xxx
, сам кеш существует для оптимизации и производительности передачи данных, поэтомуno-store
почти не используется.
Примечание: вHTTP 1.0
версия,Expires
Абсолютное время поля получается с сервера.Поскольку запрос требует времени, возникает расхождение между временем запроса браузера и временем, полученным сервером при получении запроса, что также приводит к ошибке попадания в кэш.HTTP 1.1
версия, потому чтоCache-Control
значениеmax-age=xxx
серединаxxx
После того, как относительная единица времени указана в секундах, браузер получает ресурсы для запуска обратного отсчета, чтобы избежатьHTTP 1.0
Существует недостаток ошибки в кеше, попадающем в середину, чтобы быть совместимым с более низкой версией протокола HTTP, два заголовка ответа будут использоваться одновременно при нормальной разработке.HTTP 1.1
Реализация версии имеет приоритет надHTTP 1.0
.
3. Просмотр принудительного кеша через сеть
Открываем NetWork через инструменты разработчика браузера Chrome для просмотра информации о принудительном кэшировании.
Приведенное выше является ответом изображения логотипа веб-сайта Baidu, мы ясно видим, что оно совместимо сHTTP 1.0
а такжеHTTP 1.1
версия и хранится с использованием принудительного кеша10
год.
Давайте посмотрим на разницу между данными, полученными через кеш, и другими ресурсами в Сети.
На самом деле кеш хранится в двух местах: в памяти и на диске.Это определяется собственной стратегией текущего браузера, которая является относительно случайной.Будут отображаться данные, извлеченные из кеша памяти.(from memory cache)
, данные, извлеченные из кеша диска, будут отображаться(from disk cache)
.
4. Сервер NodeJS реализует принудительное кэширование
// 强制缓存
const http = require("http");
const url = require("url");
const path = require("path");
const mime = require("mime");
const fs = require("fs");
let server = http.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
pathname = pathname !== "/" ? pathname : "/index.html";
// 获取读取文件的绝对路径
let p = path.join(__dirname, pathname);
// 查看路径是否合法
fs.access(p, err => {
// 路径不合法则直接中断连接
if (err) return res.end("Not Found");
// 设置强制缓存
res.setHeader("Expires", new Date(Date.now() + 30000).toGMTString());
res.setHeader("Cache-Control", "max-age=30");
// 设置文件类型并响应给浏览器
res.setHeader("Content-Type", `${mime.getType(p)};charset=utf8`);
fs.createReadStream(p).pipe(res);
});
});
server.listen(3000, () => {
console.log("server start 3000");
});
надmime
модульныйgetType
Метод может успешно вернуть тип файла, соответствующий файлу во входящем пути, напримерtext/html
а такжеapplication/javascript
И т. д., это сторонний модуль, который необходимо установить перед использованием.
npm install mime
Согласовать кеш
1, процесс согласования кэша
Кэш согласования также называется кешем сравнения.После установки кеша согласования, когда сервер впервые обращается к серверу для получения данных, сервер возвращает данные и идентификатор кеша в браузер, а клиент сохраняет данные и идентификатор в базе данных кеша.Следующий запрос Когда данные изменяются, он сначала пойдет в кеш, чтобы вынуть идентификатор кеша и отправить его на сервер для запроса.Когда данные сервера изменяются, идентификатор будет обновляется, поэтому сервер получает для сравнения идентификатор, отправленный браузером. Это же означает, что данные не изменились. Если он изменен, браузер будет обращаться к кешу для получения данных. Если идентификатор отличается, значит что сервер изменил данные, поэтому новые данные и новый идентификатор будут возвращены в браузер, а браузер сохранит новые данные и идентификатор в кеше и договорится.Процесс кэширования выглядит следующим образом.
Разница между согласованным кешем и принудительным кешем заключается в том, что согласованный кеш должен связываться с сервером каждый раз, когда делается запрос, а код состояния, возвращаемый сервером кеша обращений, больше не используется.200
, но304
.
2. Согласуйте флаг оценки кэша
Обязательный кеш предназначен для управления доступом к серверу через время истечения срока действия, а кеш согласования должен каждый раз взаимодействовать с сервером для сравнения идентификатора кеша.HTTP 1.0
версия иHTTP 1.1
Версии тоже разные.
существуетHTTP 1.0
версия, сервер проходитLast-Modified
Заголовок ответа используется для установки идентификатора кеша, обычно в качестве значения берется время последней модификации (абсолютное время) запрошенных данных, а браузер получает возвращенные данные и идентификатор и сохраняет их в кеше, и запрос будет автоматически отправлен повторно.If-Modified-Since
Заголовок запроса, значение — это время последней модификации (идентификатор), возвращенное ранее, и сервер забирает его.If-Modified-Since
Значение сравнивается со временем последней модификации данных, если время последней модификации большеIf-Modified-Since
Значение , указывающее, что оно было изменено, затем передатьLast-Modified
Заголовок ответа возвращает новое время последнего изменения и новые данные, в противном случае он не изменяется, и возвращается код состояния.304
Сообщите браузеру, чтобы он попал в кеш.
существуетHTTP 1.1
версия, сервер проходитEtag
Заголовок ответа используется для установки идентификатора кеша (уникальный идентификатор, как отпечаток пальца, правила генерации определяются сервером), браузер получает данные и уникальный идентификатор и сохраняет их в кеше.If-None-Match
Заголовок запроса приносит серверу уникальный идентификатор, а сервер извлекает уникальный идентификатор и сравнивает его с предыдущим, если он отличается, значит он был изменен, и возвращаются новый идентификатор и данные, если они совпадают, возвращается код состояния.304
Сообщите браузеру, чтобы он попал в кеш.
Блок-схема стратегии кэширования согласования HTTP выглядит следующим образом:
Примечание. При использовании согласованного кэшаHTTP 1.0
Версия пока не очень надежная.Допустим файл удаляется после добавления одного символа, файл эквивалентен без изменений, но изменилось время последней модификации, это будет считаться модификацией, должно попасть в кеш, но сервер повторно отправляет данные, поэтомуHTTP 1.1
используется вEtag
Уникальный идентификатор генерируется на основе содержимого файла или аннотации, что гарантирует, что до тех пор, пока содержимое файла остается неизменным, кэш будет поражен.HTTP 1.1
Реализация версии имеет приоритет надHTTP 1.0
.
3. Просмотр кэша согласования через сеть
Мы также открываем NetWork через инструменты разработчика браузера Chrome, чтобы просмотреть информацию о кэше согласования.
Запросите информацию заголовка запроса сервера еще раз:
Информация заголовка ответа, попадающая в кэш согласования:
Давайте посмотрим на разницу между данными, полученными через кеш согласования, и первой загрузкой в Сети.
Первый запрос:
Запрос после кеша:
Сравнив два рисунка, мы можем обнаружить, что код состояния, когда кеш согласования вступает в силу, выглядит следующим образом:304
И размер пакета и запрошенное время значительно уменьшается, потому что сервер только во время идентификатора возврата, чем последнийheader
часть, браузер уведомляется об использовании кеша через код состояния, и больше нет необходимости возвращать основную часть сообщения в браузер.
4. Сервер NodeJS реализует кеш согласования
// 协商缓存
const http = require("http");
const url = require("url");
const path = require("path");
const mime = require("mime");
const fs = require("fs");0
const crytpo = require("crytpo");
let server = http.createServer((req, res) => {
let { pathname } = url.parse(req.url, true);
pathname = pathname !== "/" ? pathname : "/index.html";
// 获取读取文件的绝对路径
let p = path.join(__dirname, pathname);
// 查看路径是否合法
fs.stat(p, (err, statObj) => {
// 路径不合法则直接中断连接
if (err) return res.end("Not Found");
let md5 = crypto.createHash("md5"); // 创建加密的转换流
let rs = fs.createReadStream(p); // 创建可读流
// 读取文件内容并加密
rs.on("data", data => md5.update(data));
rs.on("end", () => {
let ctime = statObj.ctime.toGMTString(); // 获取文件最后修改时间
let flag = md5.digest("hex"); // 获取加密后的唯一标识
// 获取协商缓存的请求头
let ifModifiedSince = req.headers["if-modified-since"];
let ifNoneMatch = req.headers["if-none-match"];
if (ifModifiedSince === ctime || ifNoneMatch === flag) {
res.statusCode = 304;
res.end();
} else {
// 设置协商缓存
res.setHeader("Last-Modified", ctime);
res.setHeader("Etag", flag);
// 设置文件类型并响应给浏览器
res.setHeader("Content-Type", `${mime.getType(p)};charset=utf8`);
rs.pipe(res);
}
});
});
});
server.listen(3000, () => {
console.log("server start 3000");
});
В приведенном выше коде содержимое файла считывается через читаемый поток и передается черезcrypto
модуль выполненmd5
Зашифрованный результат используется в качестве уникального идентификатора, который гарантирует, что, пока содержимое файла остается неизменным, он попадет в кеш, совместимый сHTTP 1.0
а такжеHTTP 1.1
Две версии, если одна удовлетворена, возвращаются напрямую304
Сообщите браузеру, чтобы он попал в кеш.
Примечание: На самом деле не рекомендуется шифровать содержимое прочитанного файла.Если прочитан большой файл, после чтения содержимого файла и выполненияmd5
Процесс шифрования занимает очень много времени, поэтому в процессе разработки необходимо выбрать метод, который может гарантировать производительность сервера в соответствии с реальной ситуацией в бизнесе для создания уникального идентификатора, например, в соответствии с резюме файла.
Суммировать
Чтобы сделать стратегию кэширования более надежной и гибкой,HTTP 1.0
версия иHTTP 1.1
Стратегия кеша версии будет использоваться одновременно, даже принудительный кеш и согласованный кеш будут использоваться одновременно.Для принудительного кеша сервер уведомляет браузер о времени кеша.Во время кеша, следующий запрос будет использовать кэш напрямую. Если допустимое время превышено, будет выполнено согласование. Политика кэширования для согласованного кэша будет кэшировать информацию вEtag
а такжеLast-Modified
через заголовок запросаIf-None-Match
а такжеIf-Modified-Since
Отправьте его на сервер, и сервер заодно проверит и установит новый обязательный кеш, а проверка пройдет и вернется304
Когда отображается код состояния, браузер напрямую использует кеш. Если кеш согласования также не попадает, сервер сбрасывает идентификатор кеширования согласования.