当前位置: 首页 > article >正文

HTTP 缓存技术

HTTP 缓存技术


1. 缓存概述

HTTP 缓存技术通过存储已请求资源的副本,减少重复请求、提升响应速度,并节省带宽。缓存可以在客户端、代理服务器、CDN(内容分发网络)等位置进行,能够有效提升 Web 应用的性能、降低服务器压力和加速用户访问体验。


2. 缓存的位置和类型

2.1 浏览器缓存(客户端缓存)

  • 缓存控制:通过 HTTP 头部(如 Cache-ControlExpires 等)控制缓存行为。
    • 使用 Cache-Control 控制缓存有效期。
    • 使用 Expires 指定缓存的过期时间。

在 Java 中,使用 ServletSpring 框架来设置缓存头部。

Servlet 示例

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class CacheControlServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置缓存控制头部,设置最大缓存时间为 1 小时
        response.setHeader("Cache-Control", "max-age=3600");
        response.setHeader("Expires", "Wed, 21 Oct 2023 07:28:00 GMT");

        // 设置响应内容
        PrintWriter out = response.getWriter();
        out.println("This response is cached for 1 hour.");
    }
}

Spring 示例
在 Spring 控制器中设置缓存头部:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.http.ResponseEntity;

@RestController
public class CacheController {

    @GetMapping("/cache")
    public ResponseEntity<String> getCachedResponse() {
        return ResponseEntity.ok()
                .header("Cache-Control", "max-age=3600")  // 设置最大缓存时间为 1 小时
                .header("Expires", "Wed, 21 Oct 2023 07:28:00 GMT")  // 设置过期时间
                .body("This response is cached for 1 hour.");
    }
}

2.2 代理缓存(Proxy Cache)

  • 代理缓存是指代理服务器在处理客户端请求时缓存资源,以便其他客户端可以共享该资源,减少重复请求。

例如,设置代理缓存:

response.setHeader("Cache-Control", "public, max-age=3600");  // 允许代理服务器缓存

2.3 CDN 缓存(Content Delivery Network)

  • CDN 缓存:CDN 节点缓存资源并分发到全球用户,减少请求延迟并加速资源加载。

在 Java 中,通常通过设置 Cache-Control 头部和 CDN 配置来使用缓存:

response.setHeader("Cache-Control", "public, max-age=86400");  // 资源缓存 24 小时

2.4 服务器端缓存

  • 内存缓存:可以使用如 RedisMemcached 等缓存工具来缓存数据。
  • 文件缓存:将动态生成的页面或数据存储为文件,避免重复计算。

Redis 缓存(Java 示例)
使用 Jedis(Redis 客户端)来缓存数据:

import redis.clients.jedis.Jedis;

public class RedisCacheExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost");

        // 设置缓存
        jedis.set("popular_items", "item1, item2, item3");

        // 获取缓存
        String cachedData = jedis.get("popular_items");
        System.out.println("Cached Data: " + cachedData);
    }
}

2.5 移动端缓存

  • 移动端通常通过本地存储(如 SharedPreferences、SQLite)来缓存数据。
  • 在 Java 后端与移动端的接口中,可以通过设置正确的 HTTP 头部来支持缓存。

例如,可以使用类似以下的方式向移动端应用发送缓存头:

response.setHeader("Cache-Control", "max-age=86400");  // 缓存 1 天

2.6 Web 应用缓存(Service Worker)

  • Web 应用可以通过 Service Worker 来缓存资源,实现离线功能。
    • Java 后端可以为前端提供静态资源,这些资源可以通过 Service Worker 进行缓存。

Service Worker(前端 JS 示例)

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open('my-cache').then((cache) => {
            return cache.addAll([
                '/index.html',
                '/styles.css',
                '/app.js',
            ]);
        })
    );
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((cachedResponse) => {
            return cachedResponse || fetch(event.request);
        })
    );
});

3. 常见 HTTP 头部字段

3.1 Cache-Control

  • 控制浏览器缓存的行为,常用指令包括:
    • max-age=<seconds>:资源最大缓存时间(秒)。
    • public:资源可以被任何缓存存储(浏览器、代理服务器)。
    • private:资源仅能被客户端缓存。
    • no-cache:需要重新验证资源有效性。
    • no-store:禁止缓存。

在 Java 后端中可以通过设置 Cache-Control 来控制缓存:

response.setHeader("Cache-Control", "max-age=86400");  // 缓存 1 天

3.2 Expires

  • 指定资源的过期时间,过期后浏览器必须重新向服务器请求资源。
response.setHeader("Expires", "Wed, 21 Oct 2023 07:28:00 GMT");

3.3 Last-Modified

  • 服务器返回资源的最后修改时间。客户端可以通过 If-Modified-Since 请求头向服务器确认资源是否更新。

Java 示例

response.setHeader("Last-Modified", "Wed, 21 Oct 2023 07:28:00 GMT");

3.4 ETag

  • 资源的唯一标识符,通常是资源内容的哈希值。客户端可以通过 If-None-Match 请求头验证缓存是否更新。
response.setHeader("ETag", "abc123");

4. 缓存策略

4.1 强缓存(Strong Cache)

  • 在缓存有效期内,客户端直接使用缓存,不会向服务器发送请求。
    • Cache-ControlExpires 控制。
response.setHeader("Cache-Control", "max-age=86400");  // 缓存 1 天

4.2 协商缓存(Conditional Cache)

  • 客户端存储缓存,但每次请求前会向服务器确认资源是否更新。如果没有更新,服务器返回 304 状态码。
    • 通过 ETagLast-Modified 验证。

Java 示例:检查资源是否修改

String lastModified = "Wed, 21 Oct 2023 07:28:00 GMT";
response.setHeader("Last-Modified", lastModified);

String ifModifiedSince = request.getHeader("If-Modified-Since");
if (ifModifiedSince != null && ifModifiedSince.equals(lastModified)) {
    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);  // 返回 304 状态码
    return;
}

5. 缓存管理和挑战

5.1 缓存失效

  • 缓存内容可能过时,必须确保在资源更新时及时清除或更新缓存,避免展示过时的数据。

5.2 缓存一致性

  • 在分布式缓存系统中,确保缓存节点之间的一致性是个挑战。必须保持缓存数据与源数据同步。

5.3 安全性问题

  • 对于敏感信息(如账户、支付数据等),需要确保数据不被缓存,避免泄露。

6. 缓存优化策略

6.1 设置合理的缓存时间

  • 根据资源的更新频率设置 max-ageExpires,静态资源缓存时间长,动态资源缓存时间短。
response.setHeader("Cache-Control", "max-age=3600");  // 缓存 1 小时

6.2 使用版本化文件

  • 通过版本号或哈希值(如 app.js?v=2)确保资源更新时强制浏览器重新加载最新版本。

http://www.kler.cn/a/412103.html

相关文章:

  • 如何设计和实现通用唯一 Code 生成方法
  • day11_JS初识_语法
  • NLP论文速读(剑桥大学出品)|分解和利用专家模型中的偏好进行改进视觉模型的可信度
  • mvn-mac操作小记
  • oracle会话追踪
  • 【CSP CCF记录】201809-2第14次认证 买菜
  • Cannot find a valid baseurl for repo: centos-sclo-rh/x86_64
  • Linux的前台进程和后台进程
  • Git旧文件覆盖引发思考
  • Day 27 贪心算法 part01
  • 排序算法(六)--堆排序
  • Linux17 Git 指令
  • NIO三大组件
  • OpenAI 是怎么“压力测试”大型语言模型的?
  • C#中面试的常见问题005
  • 【ArcGIS Pro实操第10期】统计某个shp文件中不同区域内的站点数
  • 探索Python自动化新境界:Helium库揭秘
  • 三六零[601360]行情数据接口
  • Angular面试题汇总系列一
  • 玩转 Burp Suite (1)
  • 硬菜!高精度!BO-Transformer贝叶斯优化编码器多特征分类预测/故障诊断
  • 【jupyter】linux服务器怎么使用jupyter
  • Android 网络通信(三)OkHttp实现登入
  • 【es6进阶】vue3中的数据劫持的最新实现方案的proxy的详解
  • java-使用HSSFWorkbook编辑excel文件
  • 《Hello YOLOv8从入门到精通》5,颈部网络(Neck)结构、核心源码和参数调优