缓存策略优化
HTTP缓存是提升API响应速度的第一道防线。通过合理设置Cache-Control
头部,可减少重复计算和数据库查询。对于静态数据或更新频率低的资源,建议采用强制缓存:
Cache-Control: public, max-age=31536000
对于动态内容,可采用协商缓存策略:
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Cache-Control: no-cache
服务端缓存实现示例(Node.js + Redis):
app.get('/products/:id', async (req, res) => {
const cacheKey = `product_${req.params.id}`;
const cachedData = await redis.get(cacheKey);
if (cachedData) {
return res.json(JSON.parse(cachedData));
}
const product = await db.query('SELECT * FROM products WHERE id = ?', [req.params.id]);
await redis.setex(cacheKey, 3600, JSON.stringify(product));
res.json(product);
});
适用场景:
– 高频读取低频更新的数据
– 计算密集型操作结果缓存
– 地理位置等时效性要求不高的数据
注意事项:
– 缓存雪崩预防:随机过期时间
– 缓存穿透防护:布隆过滤器
– 缓存一致性维护:双删策略
数据库查询优化
N+1查询问题是API性能的常见杀手。通过预加载(Eager Loading)技术可显著减少数据库往返:
# 低效方式(Django示例)
books = Book.objects.all()
for book in books:
print(book.author.name) # 每次循环都产生查询
# 优化方案
books = Book.objects.select_related('author').all()
分页优化应避免使用OFFSET:
-- 传统分页(性能随页码下降)
SELECT * FROM orders ORDER BY id LIMIT 10 OFFSET 10000;
-- 优化方案(keyset分页)
SELECT * FROM orders WHERE id > 10000 ORDER BY id LIMIT 10;
索引设计原则:
1. 为WHERE、JOIN、ORDER BY字段建立索引
2. 遵循最左前缀匹配原则
3. 避免过度索引导致的写入性能下降
负载均衡与水平扩展
无状态设计是水平扩展的前提条件。确保API服务不依赖本地存储,会话信息应存储在外部服务如Redis中。Kubernetes部署示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-service
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
spec:
containers:
- name: api
image: api-service:1.0
env:
- name: REDIS_HOST
value: "redis-cluster"
流量分发策略对比:
– 轮询(Round Robin):简单均衡
– 最少连接(Least Connections):动态负载
– IP哈希(IP Hash):会话保持
响应压缩与最小化
Gzip压缩可减少70%以上的传输体积。Nginx配置示例:
gzip on;
gzip_types application/json;
gzip_min_length 1024;
gzip_comp_level 6;
字段过滤技术允许客户端按需获取数据。GraphQL是典型实现,REST API也可通过参数实现:
GET /users/123?fields=id,name,email
响应结构优化前:
{
"data": {
"user": {
"id": 123,
"name": "John",
"email": "[email protected]",
"address": {...},
"history": [...]
}
}
}
优化后:
{
"id": 123,
"name": "John",
"email": "[email protected]"
}
异步处理与队列
非实时操作应移出主请求流程。RabbitMQ实现示例:
// 订单创建API
@PostMapping("/orders")
public ResponseEntity createOrder(@RequestBody Order order) {
orderService.validate(order);
messageQueue.publish(new OrderCreatedEvent(order.getId()));
return ResponseEntity.accepted().build();
}
事件驱动架构优势:
– 削峰填谷应对突发流量
– 失败任务自动重试
– 服务间解耦
协议与序列化优化
HTTP/2的多路复用可减少连接开销。主要改进包括:
– 二进制分帧层
– 头部压缩(HPACK)
– 服务器推送
序列化格式选择:
– JSON:通用性强,可读性好
– Protocol Buffers:体积小,解析快
– MessagePack:二进制JSON替代
Protobuf定义示例:
syntax = "proto3";
message User {
int32 id = 1;
string name = 2;
string email = 3;
}
监控与持续优化
APM工具集成是性能优化的基础。Elastic APM配置示例:
const apm = require('elastic-apm-node').start({
serviceName: 'api-service',
serverUrl: 'http://apm-server:8200'
});
app.use(apm.middleware.express());
关键指标监控:
– 响应时间(P95/P99)
– 错误率(4xx/5xx)
– 系统资源(CPU/Memory)
– 数据库查询耗时
边缘计算与CDN
地理分布策略可减少网络延迟。Cloudflare Workers示例:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const cache = caches.default
let response = await cache.match(request)
if (!response) {
response = await fetch(request)
response = new Response(response.body, response)
response.headers.append('Cache-Control', 'max-age=3600')
event.waitUntil(cache.put(request, response.clone()))
}
return response
}
连接池管理
数据库连接池配置优化(HikariCP示例):
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/db");
config.setUsername("user");
config.setPassword("pass");
config.setMaximumPoolSize(20);
config.setConnectionTimeout(30000);
config.setIdleTimeout(600000);
HikariDataSource ds = new HikariDataSource(config);
最佳实践:
– 连接数 = (核心数 * 2) + 有效磁盘数
– 设置合理的超时时间
– 监控连接泄露
代码级优化
算法复杂度分析是基础优化手段。常见优化案例:
# O(n^2) → O(n)
def find_duplicates(arr):
seen = set()
duplicates = set()
for item in arr:
if item in seen:
duplicates.add(item)
seen.add(item)
return list(duplicates)
内存管理注意事项:
– 避免大对象频繁创建销毁
– 流式处理大数据集
– 合理使用对象池