API响应优化
概览
快速的API响应可以提升整体应用性能和用户体验。优化的重点在于有效载荷大小、缓存和查询效率。
何时使用
- API响应时间慢
- 高服务器CPU/内存使用
- 大响应有效载荷
- 性能下降
- 扩展瓶颈
指令
1. 响应有效载荷优化
// 低效响应(不必要数据)
GET /api/users/123
{
"id": 123,
"name": "John",
"email": "john@example.com",
"password_hash": "...", // ❌ 绝不应发送
"ssn": "123-45-6789", // ❌ 敏感数据
"internal_id": "xyz",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-02T00:00:00Z",
"meta_data": {...}, // ❌ 未使用字段
"address": {
"street": "123 Main",
"city": "City",
"state": "ST",
"zip": "12345",
"geo": {...} // ❌ 不需要
}
}
// 优化响应(仅需要字段)
GET /api/users/123
{
"id": 123,
"name": "John",
"email": "john@example.com"
}
// 结果:2KB → 100字节(缩小20倍)
// 稀疏字段集模式
GET /api/users/123?fields=name,email
{
"id": 123,
"name": "John",
"email": "john@example.com"
}
2. 缓存策略
HTTP缓存头:
Cache-Control:
不可变资产:Cache-Control: public, max-age=31536000
API响应:Cache-Control: private, max-age=300
不缓存:Cache-Control: no-store
重新验证:Cache-Control: max-age=0, must-revalidate
ETag:
- 响应版本的唯一标识符
- If-None-Match: 如果未更改则返回304
- 节省未更改数据的带宽
Last-Modified:
- If-Modified-Since: 如果未更改则返回304
- 简单的版本控制机制
---
应用级缓存:
数据库查询缓存:
- 缓存昂贵的查询
- TTL: 5-30分钟
- 写入时失效
- 工具:Redis, Memcached
响应缓存:
- 缓存整个API响应
- 使用Cache-Control头
- 键:URL + 查询参数
- TTL: 基于数据新鲜度
片段缓存:
- 缓存响应的一部分
- 组合多个片段
- 每个片段不同的TTL
---
缓存失效:
基于时间(TTL):
- 简单:过期后时间
- 风险:过时数据
- 最适合:非关键数据
基于事件:
- 写入时失效
- 立即新鲜
- 需要协调
混合:
- TTL + 事件失效
- 短TTL + 更改时失效
- 良好平衡
---
实现示例:
GET /api/users/123/orders
Authorization: Bearer token
Cache-Control: public, max-age=300
响应:
HTTP/1.1 200 OK
Cache-Control: public, max-age=300
ETag: "123abc"
Last-Modified: 2024-01-01
{data: [...]}
-- 下一个请求在5分钟内从缓存中获取
-- 5分钟后,使用ETag重新验证
-- 如果未更改:304未修改
3. 压缩与性能
压缩:
gzip:
比例:60-80%减少
格式:text/html, application/json
开销:CPU(小)
brotli:
比例:比gzip好20%
支持:现代浏览器(95%)
开销:更高的CPU
实现:
- 在服务器上启用
- 设置Accept-Encoding头
- 测量:压缩前后大小
- 监控:CPU影响
---
性能优化:
分页:
- 限制:每个请求20-100项
- 偏移分页:简单,大偏移慢
- 光标分页:高效,稳定
- 实现:总是使用限制
过滤:
- 服务器端过滤
- 减少响应大小
- 示例:?status=active
排序:
- 仅限服务器端
- 索引频繁排序字段
- 限制排序键到1-2个字段
预加载:
- 在一个查询中获取相关数据
- 避免N+1问题
- 示例:/users?include=posts
---
度量和监控:
跟踪:
- API响应时间(目标:<200ms)
- 有效载荷大小(目标:<100KB)
- 缓存命中率(目标:>80%)
- 服务器CPU/内存
工具:
- New Relic APM
- DataDog
- Prometheus
- 自定义日志
设置警报:
- 响应时间>500ms
- 有效载荷>500KB
- 缓存未命中峰值
- 错误率
4. 优化清单
有效载荷:
[ ] 移除敏感数据
[ ] 移除未使用字段
[ ] 实施稀疏字段集
[ ] 压缩有效载荷
[ ] 使用适当的状态码
缓存:
[ ] 设置HTTP缓存头
[ ] 实施ETags
[ ] 配置应用缓存
[ ] 缓存失效策略
[ ] 缓存监控
查询效率:
[ ] 优化数据库查询
[ ] 修复N+1查询
[ ] 优化联接
[ ] 索引就位
压缩:
[ ] 启用gzip
[ ] 启用brotli(现代)
[ ] Accept-Encoding头
[ ] Content-Encoding响应
监控:
[ ] 跟踪响应时间
[ ] 跟踪有效载荷大小
[ ] 缓存指标
[ ] 错误率
[ ] 配置警报
预期改进:
- 响应时间:500ms → 100ms
- 有效载荷大小:500KB → 50KB
- 服务器负载:80% CPU → 30%
- 并发用户:100 → 1000
关键点
- 从响应中移除不必要的数据
- 实施HTTP缓存头
- 使用ETag进行重新验证
- 分页大结果集
- 启用gzip/brotli压缩
- 监控响应时间
- 缓存昂贵的查询
- 实施稀疏字段集
- 测量前后
- 设置持续监控