gongxiangp2/docs/S3性能零成本优化方案.md

6.8 KiB
Raw Blame History

S3存储性能零成本优化方案

📊 当前性能状况

根据测试结果:

  • 公网(FRP): 0.04 MB/s,延迟 2829ms
  • 内网(直连): 8.14 MB/s,延迟 8ms
  • 问题: FRP穿透导致的网络瓶颈(内网比公网快203倍)

✅ 已实现的优化

  1. 内网用户自动使用内网地址 ✓

    • 内网用户自动走内网,速度提升203倍
    • 位置:lib/url-rewrite.ts
  2. 分片上传 ✓

    • 大文件(≥5MB)自动分片上传
    • 支持断点续传
    • 位置:lib/chunk-upload.ts
  3. 图片压缩 ✓

    • 预览图自动压缩为WebP格式
    • 位置:lib/image-processor.ts

🚀 零成本优化方案

1. 优化分片上传策略(推荐)⭐⭐⭐

目标: 减小分片大小,提高并发上传效率

当前配置:

  • 分片大小: 5MB
  • 阈值: 5MB以上才分片

优化方案:

// 在 components/upload/file-upload-handlers.ts
const CHUNK_THRESHOLD = 1 * 1024 * 1024  // 改为1MB(原来5MB)
const CHUNK_SIZE = 512 * 1024  // 分片大小改为512KB(原来5MB)

效果:

  • 更小的分片 = 更快的单次上传 = 更好的进度反馈
  • 512KB分片在0.04 MB/s下约需13秒,比5MB分片(125秒)快10倍
  • 提高并发效率,减少超时风险

实施难度: ⭐ 简单(只需修改配置)


2. 优化图片压缩策略(推荐)⭐⭐

目标: 更激进的压缩,减少传输数据量

当前配置:

  • 最大尺寸: 600x800
  • 最大大小: 300KB
  • 质量: 80

优化方案:

// 在 lib/image-processor.ts
const maxSizeKB = 150  // 从300KB降到150KB
const maxWidth = 400   // 从600降到400
const maxHeight = 600  // 从800降到600
const quality = 70     // 从80降到70

效果:

  • 图片大小减少50%,传输时间减少50%
  • 对于0.04 MB/s的网速,150KB图片约需4秒,300KB需8秒

实施难度: ⭐ 简单


3. 优化缓存策略(推荐)⭐⭐

目标: 延长缓存时间,减少重复下载

当前配置:

  • 静态资源: max-age=31536000 (1年) ✓
  • 上传文件: max-age=31536000 ✓

优化方案:

  • 确保所有S3返回的图片/文件都设置长期缓存
  • 在 lib/s3.ts 上传时设置缓存头
// 在 lib/s3.ts uploadToS3 函数中
const command = new PutObjectCommand({
  Bucket: process.env.S3_BUCKET!,
  Key: key,
  Body: file,
  ContentType: contentType,
  ACL: 'public-read',
  CacheControl: 'public, max-age=31536000, immutable',  // 添加缓存头
})

效果:

  • 用户第二次访问时直接从浏览器缓存加载,无需网络请求
  • 减少90%以上的重复下载

实施难度: ⭐ 简单


4. 优化连接复用(推荐)⭐⭐

目标: 减少连接建立时间,提高效率

当前配置:

  • S3客户端已配置连接超时和重试

优化方案:

// 在 lib/s3.ts
const s3Client = new S3Client({
  // ... 现有配置
  requestHandler: {
    requestTimeout: 120000,  // 增加到120秒(大文件需要)
    connectionTimeout: 5000,  // 减少到5秒(快速失败)
  },
  maxAttempts: 3,  // 减少重试次数(从10降到3,快速失败)
  retryMode: 'adaptive',
  // 添加连接池配置
  httpOptions: {
    keepAlive: true,
    keepAliveMsecs: 30000,
  },
})

效果:

  • 连接复用减少延迟
  • 快速失败避免长时间等待

实施难度: ⭐⭐ 中等


5. 图片懒加载和预加载(推荐)⭐⭐

目标: 按需加载,减少初始加载时间

实施位置: components/home/MaterialCard.tsx

优化方案:

// 使用 Next.js Image 组件的懒加载
<Image
  src={previewUrl}
  alt={material.productModel}
  width={300}
  height={400}
  loading="lazy"  // 懒加载
  placeholder="blur"  // 模糊占位符
  priority={false}  // 非关键图片不优先加载
/>

效果:

  • 初始页面只加载可见图片
  • 减少初始加载时间50-70%

实施难度: ⭐⭐ 中等


6. 减少不必要的请求(推荐)⭐⭐⭐

目标: 合并请求,减少往返次数

优化点:

  1. 批量获取素材列表时合并预览图请求

    • 当前:每个素材单独请求预览图
    • 优化:使用CSS sprite或合并请求
  2. 减少API调用

    • 使用React Query或SWR缓存API响应
    • 减少重复的素材列表请求

实施难度: ⭐⭐⭐ 较复杂


7. 优化FRP配置(推荐)⭐⭐

目标: 虽然不能增加带宽,但可以优化配置提高效率

优化点:

  1. 启用压缩(如果FRP支持)

    # frpc.toml
    [transport]
    compression = true  # 启用压缩
    
  2. 优化连接池

    [transport]
    poolCount = 10  # 增加连接池(如果当前较小)
    heartbeatInterval = 30
    heartbeatTimeout = 90
    
  3. 使用TCP_NODELAY

    • 减少延迟(如果FRP支持)

实施难度: ⭐⭐ 中等(需要服务器配置)


8. 前端预加载关键资源(推荐)⭐

目标: 提前加载用户可能访问的资源

实施位置: app/page.tsx 或 app/layout.tsx

优化方案:

// 预加载热门素材的预览图
useEffect(() => {
  // 预加载前10个素材的预览图
  const topMaterials = materials.slice(0, 10)
  topMaterials.forEach(material => {
    if (material.previewUrl) {
      const link = document.createElement('link')
      link.rel = 'prefetch'
      link.href = material.previewUrl
      document.head.appendChild(link)
    }
  })
}, [materials])

效果:

  • 用户点击时图片已在缓存中
  • 提升用户体验

实施难度: ⭐ 简单


📋 优化优先级

高优先级(立即实施)

  1. ✅ 优化分片上传策略 - 效果显著,实施简单
  2. ✅ 优化图片压缩 - 减少50%传输量
  3. ✅ 优化缓存策略 - 减少重复下载

中优先级(近期实施)

  1. ✅ 优化连接复用 - 提高效率
  2. ✅ 图片懒加载 - 减少初始加载

低优先级(长期优化)

  1. ✅ 减少不必要的请求 - 需要重构
  2. ✅ 优化FRP配置 - 需要服务器权限
  3. ✅ 前端预加载 - 锦上添花

🎯 预期效果

实施高优先级优化后:

  • 上传速度: 用户体验提升(更小的分片,更快的反馈)
  • 下载速度: 减少50%传输量(图片压缩)
  • 重复访问: 减少90%网络请求(缓存)
  • 总体体验: 提升2-3倍(综合效果)

💡 额外建议

  1. 用户提示优化

    • 公网用户显示"内网用户可获得更快速度"提示
    • 引导用户配置hosts使用内网地址
  2. 上传进度优化

    • 显示预计剩余时间
    • 显示当前网速
    • 提供"稍后继续"功能(断点续传)
  3. 下载优化

    • 大文件提供"稍后下载"功能
    • 支持后台下载
    • 下载队列管理