koa怎么利用缓存提高性能?

在 Koa 中利用缓存优化性能,可以通过 ​​内存缓存、HTTP 缓存、Redis 缓存、CDN 缓存​​ 等多种方式实现。以下是具体方案和代码示例:

​1. HTTP 缓存(浏览器 & CDN 缓存)​​

适用于 ​​静态资源(CSS/JS/图片)​​ 或 ​​不常变动的 API 响应​​。

通过设置 Cache-Control和 ETag头,让浏览器或 CDN 缓存响应。

​​1.1 中间件设置 Cache-Control​​

const Koa = require('koa');
const app = new Koa();

// 静态资源缓存(1小时)
app.use(async (ctx, next) => {
  if (ctx.path.startsWith('/static')) {
    ctx.set('Cache-Control', 'public, max-age=3600');
  }
  await next();
});

// API 缓存(10秒)
app.use(async (ctx, next) => {
  if (ctx.path.startsWith('/api')) {
    ctx.set('Cache-Control', 'public, max-age=10');
  }
  await next();
});

​​1.2 使用 ETag实现协商缓存​​

const etag = require('koa-etag');
const conditional = require('koa-conditional-get');

app.use(conditional()); // 支持 If-None-Match
app.use(etag()); // 自动生成 ETag

app.use(async (ctx) => {
  ctx.body = { data: 'This can be cached!' };
});

浏览器首次请求:返回 200 OK+ ETag

后续请求:浏览器发送 If-None-Match,若未变化返回 304 Not Modified

​2. 内存缓存(短期高频访问数据)​​

适用于 ​​短期高频访问但较少变动的数据​​(如配置、热门数据)。

使用 node-cache或 lru-cache实现内存缓存。

​2.1 使用 node-cache​​

const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 60 }); // 默认缓存60秒

app.use(async (ctx, next) => {
  if (ctx.path === '/api/data') {
    const cachedData = cache.get('data_key');
    if (cachedData) {
      ctx.body = { data: cachedData, source: 'cache' };
      return;
    }

    // 模拟数据库查询
    const freshData = await fetchDataFromDB();
    cache.set('data_key', freshData);
    ctx.body = { data: freshData, source: 'database' };
  }
  await next();
});

​2.2 使用 lru-cache(更高效)​​

const LRU = require('lru-cache');
const cache = new LRU({ max: 500, maxAge: 1000 * 60 }); // 最多500条,缓存1分钟

app.use(async (ctx) => {
  if (ctx.path === '/api/users') {
    const cachedUsers = cache.get('users');
    if (cachedUsers) {
      ctx.body = { users: cachedUsers, source: 'cache' };
      return;
    }

    const users = await fetchUsersFromDB();
    cache.set('users', users);
    ctx.body = { users, source: 'database' };
  }
});

​3. Redis 缓存(分布式 & 长期存储)​​

适用于 ​​多实例部署​​ 或 ​​需要持久化的缓存​​(如用户会话、热点数据)。

​3.1 使用 ioredis​​

const Redis = require('ioredis');
const redis = new Redis(); // 默认连接本地6379

app.use(async (ctx) => {
  if (ctx.path === '/api/posts') {
    const cachedPosts = await redis.get('posts');
    if (cachedPosts) {
      ctx.body = { posts: JSON.parse(cachedPosts), source: 'redis' };
      return;
    }

    const posts = await fetchPostsFromDB();
    await redis.set('posts', JSON.stringify(posts), 'EX', 60); // 缓存60秒
    ctx.body = { posts, source: 'database' };
  }
});

​3.2 使用 koa-redis-cache中间件​​

const koaRedisCache = require('koa-redis-cache');
app.use(koaRedisCache({
  prefix: 'cache:', // Redis key 前缀
  expire: 60,       // 默认缓存60秒
  passParam: 'skipCache', // 可跳过缓存的参数(如 ?skipCache=true)
}));

​4. CDN 缓存(静态资源加速)​​

适用于 ​​CSS/JS/图片等静态文件​​,减少服务器负载。

​4.1 结合 koa-static​​

const static = require('koa-static');
app.use(static('public', {
  maxAge: 86400 * 365, // 缓存1年
  immutable: true,     // 资源内容不变
}));

​4.2 Nginx 配置(增强缓存)​​

location /static/ {
  expires 1y;
  add_header Cache-Control "public, immutable";
}