对于一个信息系统的后端服务(如一个web服务),其性能优化应该如何着手?这里试图从一般性方法论的角度,给出一些思路。
一、性能优化流程
性能优化一般流程如下图所示:
二、性能指标
用来衡量一个系统的性能指标通常有:
- TPS/QPS:Transaction Per Second,每秒处理事务数量;Query Per Second,每秒请求次数。这两个指标反应的是系统吞吐量,往往用于描述系统在一定的并发压力下的性能表现。
- RT:Response Time,响应时间,执行一个请求从开始到最后收到响应数据所花费的总体时间,即从客户端发起请求到收到服务器响应结果的时间。它反应的是系统的响应速度。
一个描述系统的期望性能指标的例子:
- 无并发环境下,单次请求的响应时间小于1秒;
- 在【100用户同时操作,QPS达到500,并持续30分钟】的并发压力下,系统的TPS达到300以上,平均响应时间小于5秒,90%响应时间小于3秒。(90%响应时间意思是指90%的请求的响应时间,依据不同的性能需求,也可以指定80%RT,95%RT等等。)
三、寻找性能瓶颈及其优化对策的指导方针
按照性能优化一般流程,你需要先衡量系统目前的性能表现。所以首先你需要耗时统计与资源监控。
- 耗时统计
- 资源监控
然后你可以从三个层面去考虑如何寻找性能瓶颈及其优化策略:
- 应用层面
- 架构层面
- 运维层面
3.1 耗时统计
响应时间是一个系统最重要的性能指标之一。对于系统的用户而言,响应时间是最直接影响使用用户体验的性能参数。
我们需要首先通过日志分析等手段,确定一个请求的各阶段耗时。
例如对于典型的分层部署的后台系统,你需要首先定位耗时较长的处理分别位于哪些服务器。
web服务器?业务逻辑层服务器?DB层服务器?
3.2 分析硬件资源监控的统计数据,确定资源有无瓶颈
当我们已经明确耗时较长的处理位于哪个服务器之后,我们首先需要确认该服务器在性能测试期间的资源消耗。
- CPU负载/利用率:如果CPU负荷过高说明目前CPU资源是不足的。那么在后续的[分析程序的数据结构与算法]阶段,你需要优化运算逻辑如设计更合理的并行线程数量(通常是cpu核数×2);或者你可以直接增加CPU资源(scale up);
- 内存占用:如果内存占用过高,可能会导致交换到swarp区,进而导致性能下降。那么在后续的[分析程序的数据结构与算法]阶段,你需要优化程序设计,比如减少缓存使用,及时释放内存等;或者你可以直接增加内存(scale up)。
- 磁盘IO:磁盘IO过多会导致性能表现下降,严重时会导致相关线程阻塞。那么在后续的[分析程序的数据结构与算法]阶段,你可以考虑优化程序设计,减少IO量,减少小文件读写频率,增加缓存等等;或者你可以直接置换磁盘为SSD(scale up)。
- 网络IO:网络IO过多可能会被网络带宽限制,导致传输速度受限。那么在后续的[分析程序的数据结构与算法]阶段,你可以优化程序设计比如减小通信量;或你可以直接增加带宽(scale up)。
3.3 应用层面的优化
从应用层面考虑,我们应该对逻辑处理的数据结构与算法进行优化:
- 如果资源有瓶颈,参考[3.2 分析硬件资源监控的统计数据,确定资源有无瓶颈]中的相关记述对程序本身逻辑进行优化分析;
- 如果资源无瓶颈,则需要分析程序本身的数据结构与算法有无优化空间。
例如:
- 优化算法,采用在时间复杂度方面更具有优势的算法,例如,使用更合理的数据结构,减少循环的深度与次数,减少递归深度等;
- 有没有临界资源的竞争,例如有没有使用排它锁导致其他线程阻塞等现象;
- 对于SQL语句,要考虑SQL语句有没有优化空间,表能否优化结构比如添加索引,甚至考虑explain解析执行计划分析SQL语句;
- 其他...
3.4 架构层面的优化
从架构层面分析性能问题时,涉及到的技术较多。
这里以一般的Web站点架构(大致如下图所示)为例,说明一下我们可以考虑的切入点:
- 反向代理层性能优化(如通过参数优化增加并发能力)。
- Web站点层性能优化。参数优化增加QPS指标;是否需要使用支持异步非阻塞模式的web容器来增加单机并发能力(如webflux);是否需要水平扩展多个web站点并负载均衡来增加集群并发能力(scale out)。
- 是否需要内存数据库实现缓存层设计(如redis)。
- DB是否需要读写分离,是否需要分库分表(如sharding-jdbc)。
- 各层通信效率能否优化,有没有更高效的序列化协议(如protobuf)。
- 是否需要引入搜索引擎为数据库或非结构化数据建立反向索引实现快速检索(如elasticSearch)。
- 是否需要对业务层进行水平扩展来增加并发能力(scale out)。
- 是否需要采用分布式并行运算框架,解决特殊场景的单机性能上限问题。
- DB层是否需要使用其他的NOSql数据库从而提升非OLTP场景的性能表现。
3.5 运维层面的优化
运维层面的优化主要是各种组件服务器的性能相关参数优化。
这里列举了常见的组件服务以及linux内核等参数优化的例子:
- DB参数优化 : 对于DB服务器,有无性能相关参数可以优化。比如存储引擎,缓冲池大小等等。
- JVM参数优化 : 对于java应用,JVM参数是否可以优化。如GC算法,堆栈分配等等。同时,可以增加GC日志分析是否发生了过多的full GC。
- linux内核参数优化 : 对于linux服务器的内核参数,应当根据业务环境特性及服务器硬件配置来设置合理的值。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。