从5秒到34ms 我如何让API接口的延迟降低97%

18 阅读4分钟

前言

后端最经常遇到的问题就是API接口请求延迟,代码一看没啥问题,业务逻辑处理速度并不慢,但就是延迟非常严重,关于这个问题,我最近正好做了个个人项目模拟支付回调接口扣减库存这个链路,正好有机会分享一下自己降低延迟的几个方法。以下是各版本压测/负载测试时P95延迟,虽然在5.0.0起从极限压测改为负载测试但还是能测出性能瓶颈,整个系统全部打爆反倒不好排查。 P95.png

升级服务器配置

我的两个服务一直都是限制单核CPU+512M内存分别在2台4C8G的服务器运行,但基础设施服务器运行着ETCD、Consul和MySQL,每一个都是吃硬件资源的巨兽,基础设施服务器配置仅2核4G,在2.0.0引入DTM分布式事务和ETCD分布式锁,ETCD疯狂刷盘又吃内存,加上DTM调度分布式事务操作MySQL数据库,使得服务器资源极度紧张,压测不到7分钟CPU快速飙升到80%以上。于是在3.0.0升级到4核8G解决资源紧张的问题,同时升级到事件驱动架构进一步提升性能。

完善可观测性

可观测链路不完善会极大地影响性能调优。特别是事件驱动架构,链路追踪不完善的情况下根本不知道到底从哪里入手,只能走一步看一步。

首先是日志,从网关到GRPC请求、发布订阅都要记录,至少得记录耗时,异步生产者还要增加在途消息数,以确定是消息积压在服务还是kafka的故障。

第二步是链路追踪和监控,同样也是全部要接上,如果这些都没有问题就要考虑其他因素。

有了这些可观测链路,我们就知道是数据库配置不合理还是服务本身/其他因素。

在4.0.0及以前的版本没有完善可观测性所以几乎是凭经验来优化,通过链路追踪和监控我就知道是发布消息耗时较长,于是在5.0.0开发结束前将同步生产者改为异步生产者,所以图中可以看到P95延迟降至100ms以下。

迁移自建基础设施到云服务

如果不是大厂和一些特殊需求,自建的基础设施存在可用性和稳定性差的问题,要是和服务部署在同一台主机上会和服务争抢硬件资源,现在是云原生的时代不要再想着自建/自研,更不要想着去自研一套组件!自搞一套四不像的可观测链路接不上云服务,和主流开源社区脱节,未来升级架构会非常困难!我起初也是自建Jaeger和ES并为此多买了一台服务器,6.2.0直接采用Opentelemetry接入阿里云,因为采样率很低,一个月的免费额度完全够用,日志也是按比例采集,接入阿里云SLS以后直接撤下一台服务器还不用担心基础设施爆掉。要知道服务多起来的话基础设施也会被打爆,如果你让它们运行在K8S集群里还会被杀死,所以能用云服务尽量使用,不要想着什么都去自研!

调整Linux内核参数

当你在日志、链路追踪观察到每一步操作执行很快但API接口仍存在耗时很长的长尾请求时,Linux内核参数配置不当是最大的可能!系统默认能接收请求的数量很小,这部分需结合自己的服务器配置来调整,调整后可以极大地释放出硬件性能,让服务器处理更多请求。

总结

API接口性能调优需要考虑到方方面面,不只是加机器那么简单,从我的实践上来看,加机器的同时也要注意其他方面的优化,比如Linux内核参数及资源争抢,尤其是资源争抢这个得结合监控和链路追踪来分析,这样才能起到事半功倍的效果。

项目地址: Go微服务项目架构演进深度实践