一、慢API描述
慢api的原因可能有:数据库性能,业务代码算法复杂度高,内存泄漏,依赖资源,网络资源等请求
解决需要从分析复现开始:
必现需要:curl,操作账号,环境
偶发需要:请求时间,操作参数
api耗时预期:
历史99、95平均耗时
初次上线时间、迭代后响应时间
二、 慢api的原因分析和工具验证
1 skywalking链路追踪 (低代码入侵,接入方便。但依赖服务端性能,开销大)
依赖资源类瓶颈{数据库,应用服务},优化下游接口,SQL。
无优化空间的超大批量请求接口(参数List数量 > 1000)考虑拆分分区并行
接口、数据库类循环请求浪费连接资源,时间复杂度O(n)。建议使用批量请求(例如: in 查询),in的参数数量不可控时需要考虑拆分分区。时间复杂度尽量设计O(logn)
2 traceId log
复杂高耦合应用业务,添加全局日志TranceId还原调用堆栈,由请求的root服务生成全链路TraceId,检索日志排查。
全链路追踪开源框架都支持traceId,如Skywalking,阿里EagleEye,携程CAT。
3 arthas诊断
arthas.aliyun.com/doc/#%E8%83…
常见的命令有:
追踪耗时分析:trace
监控实时面板 dashboard
打印线程id thread n
查找JVM里已加载的类 sc/sm
反编译代码 jad
......
火焰图生产分析
4 监控看板grafance、阿里云
三、性能瓶颈解决
1 数据库:老生常谈(索引建立优化,执行计划分析),统计类的可以按单位分表分区
2 内存:超大批量的请求,分区分批执行
3 线程池、连接池资源
全局ForkJoinPool的阻塞风险。建议CPU密集型任务使用。IO阻塞型任务使用自定义线程池。
CPU核心数>2情况下使用全局ForkJoin线程池,同样有全局阻塞风险。
CPU核心数<2情况下退化为每次执行新建new Thread()线程。
建议搭配自定义线程池使用
四、优化节奏
1 优化过程
被优化代码保留n个迭代版本,持续观察
2 优化发布兜底
使用配置开关控制,方便接口测试数据对比与回滚。核心逻辑的重构可以使用更为复杂的灰度开关,如百分比,部分用户,区域应用