导语:
高吞吐、低延迟 Java 服务在高峰期容易被 GC、I/O、队列背压拖垮。本文给出可操作的方案:ZGC 调优、零拷贝 I/O、容量与限流预案、观测与回滚。
1. GC 策略与参数
- 版本:JDK17+ 优先 ZGC;需要小抖动且大堆时优先。
- 参数示例:
-XX:+UseZGC -XX:ConcGCThreads=4 -XX:ZCollectionInterval=1 -XX:+ZGenerational。 - 观测:暴露 GC 暂停、并发时间、晋升失败;在看板设告警。
- 验证:压测对比 ZGC 与 G1 的 P99 延迟与 CPU 占用,选取基线。
2. 内存与对象策略
- 避免热点装箱与短生命周期对象;使用
ThreadLocal慎重,监控局部堆。 - 缓冲:使用
ByteBuffer.allocateDirect或 Netty Pooled ByteBuf,减少堆内复制。 - 大对象:超过 1MB 的负载,考虑分片或流式处理,降低单次分配压力。
3. I/O 与协议
- Netty:启用 EPOLL/KQueue,调整
write_buffer_water_mark,避免背压扩散。 - HTTP/2:开启压缩白名单、流量控制;对大响应支持分块/流式。
- 零拷贝:文件下载使用
FileRegion/sendfile;消息传输使用mmap+direct buffer。
4. 容量、限流与隔离
- 容量模型:按 QPS、P99、CPU/内存、外部依赖时延做反压阈值;把模型写入 Runbook。
- 限流:令牌桶+突发上限,暴露拒绝计数与原因;对外部依赖设置舱壁隔离与超时。
- 灰度:1%→10%→50%→全量,监控 GC、线程池队列、水位、外部依赖 P99。
5. 线程池与队列
- 线程池分级:计算、I/O、阻塞隔离;核心/最大/队列长度基于压测数据设定。
- 拒绝策略:自定义记录上下文,必要时降级返回缓存/兜底响应。
- 诊断:暴露队列长度、活跃线程、任务耗时分布,避免盲目扩容。
6. 依赖与超时
- 外部依赖:为每个依赖设置
timeout/retry/circuit-breaker,并观测错误率与超时分布。 - 断路器:错误率/超时超阈值自动降级,记录熔断/恢复时间线。
- 连接池:按依赖设并发上限;长连接保活与探活间隔合理配置。
7. 观测与压测
- 指标:GC 暂停/并发时间、堆使用、线程池队列、限流/拒绝次数、P50/P90/P99。
- 日志:结构化上下文(trace_id、版本、租户),易于对比新旧版本。
- 压测:按核心路由压测,确认 P99 与 CPU/内存/IO 占用;形成容量基线。
8. 部署与回滚
- 启动探针:启动耗时、类加载、预热路由;失败立即回滚。
- 回滚策略:配置与镜像双通道;回滚后 30 分钟验证核心指标。
- 证据包:压测报告、参数、容量模型、限流/超时配置、回滚演练记录。
9. 快速核查
- ZGC 参数与观测就绪,压测对比过 G1。
- 线程池与限流/舱壁隔离上线,外部依赖有超时与断路器。
- 观测看板与回滚脚本可用,容量模型明确。
结语:
把 GC、I/O、容量与观测做成固定套路,低延迟 Java 服务才能在高峰期保持稳定与可回滚。