性能
性能是一项特性。为 P99 设计,而非平均值。先测量再优化——直觉几乎总是错误地判断时间的消耗点。
规则
- 先分析再优化。 猜测热点路径会浪费数天时间。优先使用火焰图、APM 跟踪或
EXPLAIN ANALYZE。 - 消除 N+1 查询。 服务代码中最大的延迟来源。优先使用连接、批量获取或
IN (...),而不是逐行查询。 - 对每个列表端点进行分页。 无界的结果集最终会导致 Pod OOM 或使数据库饱和。对于大表,默认使用游标分页。
- 在查询谓词上建立索引,而非每个列。 每一个额外的索引都会减慢写入速度并增加存储开销。仅在已知查询需要时添加索引。
- 只投影所需的列。
SELECT *到宽泛的 DTO 会浪费网络、内存和垃圾收集。为列表 API 返回窄投影。 - 缓存读取频繁的幂等数据。 但要在添加缓存之前决定失效策略——没有逐出计划的缓存是一个 Bug 工厂。
- 显式设置连接和线程池大小。 默认值很少适合你的工作负载。根据下游容量调整大小,不要向上调整。
- 批量执行出站调用。 一个包含 100 项的请求在延迟、CPU、数据库连接等所有方面都优于 100 个包含 1 项的请求。
- 避免同步的远程调用链。 延迟会累积。并行扩展,或将工作异步处理。
- 保持负载小巧。 压缩响应,修剪未使用的字段,在需要时使用二进制协议(gRPC、Protobuf)。
红牌
- 循环查询数据库。
- 返回“所有记录”的 API。
- 没有 TTL 且没有失效策略的缓存。
- 生产环境中线程池/连接池设置为框架默认值。
- 只显示平均值(无 P95/P99)的延迟仪表盘。