真正的高可用高并发架构,只有在压测中才能显示合理性和不合理性。有时候我们怀疑积压来自于服务,其实可能来自于数据,或者缓存或者消息队列。

  • 确认核心链路的范围:纵向看,深度到哪里(哪里已经不是本架构域需要关注和改造的范围,哪里需要 mock);横向看,一个请求会涉及多宽的 scope(服务的宽幅)。产出是:需要关注的服务和拓扑结构。
  • 寻找压测指标:容量应该在什么条件下摸到多高。高度由现在的日常业务高峰和大促的流量增长综合评估得出,首先确定业务系统应该支持的 qps/tps 数量。然后考虑容灾等级,即允许在几个机房、几台机器挂掉以后,服务还能正常运行。如果一个服务应该支持的日常峰值(考虑大促),乘以冗余数量(如果是两地三中心,应该考虑将单机房的压测峰值乘以 3)。
  • 确定压测过程中压测指标:
    • VM 性能指标项:
      • fullgc 次数
      • gc time(总数和平均值)
      • gc count(注意和同环比看是不是显著增加,是不是有可疑的波动)
      • block 状态线程数(看看系统是不是已经达到吞吐瓶颈了)
    • 服务性能指标项:
      • 接口 TP999 的响应耗时(没有办法统计这项指标的可以看 MAX 和 AVG)
      • 服务错误率(最好看监控中出现的错误出现的次数和种类,如果有错误细节就更好)
    • 数据库性能指标项:
      • 读写性能(读 qps、写 tps)
      • 响应时间
      • 主从延迟(需要有 dba 基础设施,专门监控主从延迟时间)
    • MQ性能指标项:
    • 是否产生堆积(能否看到是哪一个消费者,消费者的哪一个 partition 产生了堆积,堆积的原因到底是单纯的吞吐线程数量不够,还是消费流程产生了瓶颈,还是出现了异常死信?)
    • 消息发送时延
    • 消息消费时延
    • 缓存指标(以 Redis 为例,Tair 同理):
      • 缓存的读写时延(是否有明显的阻塞操作,特别是 Redis 的 io 模型是单线程的 io 模型,时延直接关联吞吐)
      • 是否出现大 key
      • 是否出现内存存量暴增的方案
    • 搜索引擎:
      • 从 RDBMS 里同步数据是不是有延迟(可能受到了 MQ 之类的数据搬运工具的时延影响,也可能碰到了搜索引擎自己的索引构建瓶颈)。
      • 当前的分片模式是否能够支持压测中产生的读写。
  • 确定压测的数据范围:
    • 是否使用流量复制技术。如果使用流量复制技术,则变更请求中的什么部分,保证不会产生新的交易 - 如果压测环节出现问题,压测流量是怎么被隔离的。通常要确认数据库是否有影子表,缓存是否有影子 Category、搜索引擎是否能够单独把影子流量存在影子索引里。甚至有必要使用测试的业务线,使用测试的商品、测试的结算方式等等。
    • 测试用的流量如何染色,染色的流量如何保证不丢-特别要小心线程池中丢失测试标记,和 Java 组件(缓存、数据库、搜索引擎)不能识别和传递压测流量的问题,这时候可能要考虑对数据库中间件,缓存中间件等读写 proxy 进行压测改造。
  • 确定预案:
    • 如果压测出现问题,是否有关闭压测的能力。
    • 压测各个环节是否可以自动采集相关时间范围或者 trace 范围的异常。
    • 如果压测出现问题,所有的中间件是否有自动扩容的能力。
    • 如果压测出现问题,所有的服务是否有限流和熔断的能力。
  • 测试产出压测报告:
    • 压测中要监控的指标的截图或者表格
    • 错误的内容
    • 数据比对:所有压测流量是否都准确地落入链路的各个环节。
  • 要记得关闭压测流量以后,消除影响:该缩容的缩容,该滚动重启的重启 - 清理缓存。