加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、容器安全、数据加密、云日志、云数据迁移!
当前位置: 首页 > 教程 > 正文

运用node如何实现缓存

发布时间:2023-08-02 10:05:08 所属栏目:教程 来源:转载
导读:   为大家详细介绍“用node如何实现缓存”,内容详细,步骤清晰,细节处理妥当,希望这篇“用node如何实现缓存”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入
  为大家详细介绍“用node如何实现缓存”,内容详细,步骤清晰,细节处理妥当,希望这篇“用node如何实现缓存”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。
 
  缓存原理
 
  浏览器缓存的基本原理是将静态资源(如 CSS、JavaScript、图片等)缓存到本地,当页面再次请求这些资源时,直接从本地获取,而不是重新从服务器下载。这可以减少页面的加载时间和减轻服务器负担,提高用户体验。
 
  在 HTTP 协议中,浏览器缓存可以通过两种机制实现:强缓存和协商缓存。
 
  强缓存
 
  Expires字段:
 
  值为服务端返回的到期时间,可能因为服务端和客户端时间不同而造成缓存命中误差
 
  Cache-Control(替代方案)
 
  public:所有内容都被缓存(客户端和代理服务器都可被缓存)
 
  private:只缓存到私有缓存中(客户端)
 
  no-cache:与服务端确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。
 
  no-store:值不缓存
 
  must-revalidation/proxy-revalidation:如果缓存内容失效,则请求必须发送到服务器已进行重新验证
 
  max-age=xxx:缓存内容在xxx秒后失效,这个选项只能在http1.1使用, 比last-Modified优先级更高
 
  last-Modified(上次修改日期)
 
  last-Modified:保存于服务器中,记录该资源上次修改的日期(不能精确到秒,如果在数秒内多次修改,可能会导致错误命中缓存)
 
  if-modified-since:保存于客户端中,请求被携带并与服务端的last-Modified比较,相同则直接命中缓存返回304状态码
 
  koa实现强缓存
 
  const Koa = require('koa');
 
  const app = new Koa();
 
  // 设置 expires方案
 
  const setExpires = async (ctx, next) => {
 
    // 设置缓存时间为 1 分钟
 
    const expires = new Date(Date.now() + 60 * 1000);
 
    ctx.set('Expires', expires.toUTCString());
 
    await next();
 
  }
 
  // Cache-Control方案(优先执行)
 
  const setCacheControl = async (ctx, next) => {
 
    // 设置缓存时间为 1 分钟
 
    ctx.set('Cache-Control', 'public, max-age=60');
 
    await next();
 
  }
 
  // Last-Modified方案
 
  const setLastModified = async (ctx, next) => {
 
    // 获取资源最后修改时间
 
    const lastModified = new Date('2021-03-05T00:00:00Z');
 
    // 设置 Last-Modified 头
 
    ctx.set('Last-Modified', lastModified.toUTCString());
 
    await next();
 
  }
 
  const response = (ctx) => {
 
    ctx.body = 'Hello World';
 
  }
 
  // 跟Last-Modified方案相对应
 
  const lastModifiedResponse = (ctx) => {
 
    // 如果资源已经修改过,则返回新的资源
 
    if (ctx.headers['if-modified-since'] !== ctx.response.get('Last-Modified')) {
 
       response(ctx)
 
    } else ctx.status = 304;
 
  }
 
  app.get('/getMes', setExpires, response);
 
  app.listen(3000, () => console.log('Server started on port 3000'));
 
  协商缓存(浏览器和服务器通过一个值进行协商判断)
 
  Etag/if-None-Match
 
  Etag:服务器根据请求的资源计算一个哈希值(也可以是其他算法,代表一个资源标识符) 并返回给浏览器,下次浏览器请求该资源时通过if-None-Match字段将Etag发送给服务器
 
  用node如何实现缓存
 
  Last_Modified和if-Modified-Since
 
  last-Modified:保存于服务器中,记录该资源上次修改的日期(不能精确到秒,如果在数秒内多次修改,可能会导致错误命中缓存)
 
  if-modified-since:保存于客户端中,请求被携带并与服务端的last-Modified比较,相同则直接命中缓存返回304状态码
 
  协商缓存ETag和Last-Modified区别:
 
  ETag 是服务器为资源分配的唯一标识符,而 Last-Modified 是服务器报告的资源的最后修改时间。
 
  ETag 可以使用任何算法生成,例如哈希,而 Last-Modified 只能使用特定的时间格式(GMT)。
 
  ETag 的比较是强验证器(exact-match validator),需要完全匹配,而 Last-Modified 的比较是弱验证器(weak validator),只需要在同一秒钟内相同即可。
 
  ETag 适用于所有类型的资源,而 Last-Modified 只适用于不常更改的资源,例如图片、视频等。
 
  对于经常更新的资源,ETag 更适合,因为它可以更准确地检测资源是否已经被修改;而对于不经常更新的资源,Last-Modified 更适合,因为它可以减少服务器负载和网络流量。
 
  koa实现协商缓存
 
  const Koa = require('koa');
 
  const app = new Koa();
 
  // 设置 eTag方案
 
  const setExpires = async (ctx, next) => {
 
    // 设置缓存时间为 1 分钟
 
    const maxAge = 60;
 
    ctx.set('Cache-Control', `public, max-age=${maxAge}`);
 
    // 设置 ETag 头
 
    const etag = 'etag-123456789';
 
    ctx.set('ETag', etag);
 
    await next();
 
  }
 
  // Last-Modified方案
 
  const setLastModified = async (ctx, next) => {
 
    // 设置缓存时间为 1 分钟
 
    const maxAge = 60;
 
    ctx.set('Cache-Control', `public, max-age=${maxAge}`);
 
    // 设置 Last-Modified 头
 
    const lastModified = new Date('2021-03-05T00:00:00Z');
 
    ctx.set('Last-Modified', lastModified.toUTCString());
 
    await next();
 
  }
 
  const response = (ctx) => {
 
    ctx.body = 'Hello World';
 
  }
 
  // 跟Etag方案对应
 
  const etagResponse = (ctx) => {
 
    // 如果 ETag 头未被修改,则返回 304
 
    if (ctx.headers['if-none-match'] === ctx.response.get('ETag')) {
 
      ctx.status = 304;
 
    } else ctx.body = 'Hello World';
 
  }
 
  // 跟Last-Modified方案相对应
 
  const lastModifiedResponse = (ctx) => {
 
    // 如果资源已经修改过,则返回新的资源
 
    if (ctx.headers['if-modified-since'] !== ctx.response.get('Last-Modified')) {
 
       response(ctx)
 
    } else ctx.status = 304;
 
  }
 
  app.get('/getMes', setExpires, response);
 
  app.listen(3000, () => console.log('Server started on port 3000'));
 
  koa使用哈希计算Etag值:
 
  const Koa = require('koa');
 
  const crypto = require('crypto');
 
  const app = new Koa();
 
  // 假设这是要缓存的资源
 
  const content = 'Hello, world!';
 
  app.use(async (ctx) => {
 
    // 计算资源的哈希值
 
    const hash = crypto.createHash('md5').update(content).digest('hex');
 
    // 设置 ETag 头
 
    ctx.set('ETag', hash);
 
    // 判断客户端是否发送了 If-None-Match 头
 
    const ifNoneMatch = ctx.get('If-None-Match');
 
    if (ifNoneMatch === hash) {
 
      // 如果客户端发送了 If-None-Match 头,并且与当前资源的哈希值相同,则返回 304 Not Modified
 
      ctx.status = 304;
 
    } else {
 
      // 如果客户端没有发送 If-None-Match 头,或者与当前资源的哈希值不同,则返回新的资源
 
      ctx.body = content;
 
    }
 
  });
 
  app.listen(3000);
 
  缓存执行流程:
 
  强缓存未失效,从缓存中读取数据,cache-control优先级高于last-Modified
 
  强缓存失效,执行协商缓存,Etag的优先级会高于last-Modified
 
  缓存未失效服务器返回304状态码,客户端从缓存中读取数据
 
  缓存已失效则返回资源和200状态码
 
  强缓存和协商缓存的使用?
 
  强缓存通常在浏览器中缓存静态资源(如 CSS、JavaScript、图片等),以减少页面的加载时间和减轻服务器负担。
 
  协商缓存通常用于缓存动态资源(如 HTML 页面、API 数据等),以减少服务器的负担和网络带宽的消耗。
 
  在实际应用中,强缓存和协商缓存可以单独使用或一起使用。对于一些静态资源,可以只使用强缓存;对于一些动态资源,可以只使用协商缓存;对于一些经常变化的资源,可以使用强缓存和协商缓存结合使用,既可以减少服务器的负担,也可以保证及时获取到最新的资源。
 

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章