Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

前言

萌叔工作十多年,有不少服务调优的经验,在这里整理一下思路。希望对自己和同行有所帮助。

1. 发现问题

1.1 发现问题比解决问题难度更大

找出系统瓶颈和问题难度很大,一般只要能够找出且能够稳定复现,问题都能够被解决。

1.2 压测能够帮我们发现系统瓶颈,找出问题

压测不仅可以帮助我们发现系统瓶颈,还能用于发现死锁问题

1.3 尽可能细粒度的监控指标对发现问题帮助很大

讲几个容易忽略的细节

  • 使用Cache的场景,要留意Cache的命中率
  • 使用Channel的细节,要监控channel的长度,注意Channel是否写满,阻塞其它协程
  • 对于比较复杂的接口,如果延迟高,需要有tracing记录,关注到底是那个环节耗时过多
  • 对于MQ和数据库的场景,甚至还需要监控PageCache的命中率和使用情况、磁盘IO等等
  • GC 的耗时(特别是Java中Full GC)

2. 常见的思路

2.1 绝大多数服务的系统瓶颈是IO

我们接触到的绝大多数服务,都是IO型服务,影响延迟的主要因素是IO,磁盘IO、网络IO,数据库、微服务的响应延迟等等

2.2 如果CPU是瓶颈,需要有火焰图,关注是哪个环节消耗的CPU过多?每个部分占比是否合理?(注意压测)

比如是否大量的CPU时间被消耗在了锁竞争、上下文切换、垃圾回收、调度等。

  • 在Golang中,由于锁中含有自旋锁,如果对锁的竞争激烈,会有大量的CPU时间被消耗在锁上。
  • 在Golang中,P设置不合理也会导致大量的上下文切换

见文章
GOMAXPROCS你设置对了吗?

2.3 某一类型的服务,往往会有一组需要额外注意的核心指标

某些特定的服务容易受到特定因素的影响,比如

  • 基于模型的分类器,压测时要特别关注它的CPU使用率是否能够跑满

见文章
AI预测模型工程化性能调优

  • 数据库服务要留意磁盘IO

2.4 GC

有GC的场景,还要特别留意GC可能带来的负面影响

2.5 日志对服务性能影响不小

写文件和写控制台的性能差不多, 每秒钟差不多30w条。假定一个请求产生30条日志,也就是说即使处理这个请求没有任何逻辑,光是打日志,QPS也就差不多1w左右。(这也是很多服务压测的QPS无法超过1w的原因)。

见文章
玩转高性能日志库ZAP(5)-异步写日志

当你不知道该怎么调优的时候,可以试试关闭所有日志看看。?

3. 常见的优化手段

3.1 串行变并发

在IO型服务非常常见

3.2 同步变异步

常见的场景是回写数据库

3.3 单条变批量

  • 比如数据需要回写数据库,可以在内存中缓存一拨,批量回写数据库,可以减少网络开销,降低数据库的开销
  • 另外像写日志文件,批量写可以减少系统调用,提高写入效率。

笔者之前曾做过测试,将日志从单条同步写改为异步批量写,吞吐能力提升了1倍多。

见文章
玩转高性能日志库ZAP(5)-异步写日志

3.4 善用Cache

在多读少写的服务中,Cache对提升服务的能力,降低延迟,效果非常显著。(别忘了监控Cache)

3.5 借鉴同行的经验

毕竟同行踩过的坑,我们还是会再踩一遍的,可以多留意github中的issue记录。

4. 其它

4.1 过早优化是万恶之源

没事别瞎折腾

4.2 越接近业务侧的优化,效果越显著

4.3 该加机器加机器,人力成本也是钱

有了一把趁手的锤子,但是又具有足够自知之明,不把所有东西都当做钉子。这种能力更是难能可贵。

5. 结尾

好多东西不整理一下,自己都快忘了。希望下次再排查问题或者调优的时候,我也能从中收益。


微信公众号

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注