服务性能记录

作者: | 更新日期:

最近做一个项目, 需要评估一下性能与瓶颈所在之处, 这里简单记录一下.

前言

随着业务的快速成长,访问量越来越高,除了对功能要求很高以外,对性能要求也越来越高。 在实际工作中,我们往往会被一些问题所困扰。

  1. 线上服务容量是多少?性能痛点在哪里? 可伸缩性和可靠性怎样? 预先知道了系统的容量,做到心中有数,才能为最终规划整个运行环境的配置提供有利的依据。

  2. 新开发的功能是否满足性能指标? 重新修改的代码会不会带来性能问题? 对服务或工具的参数修改是否有效果?
    如果在上线用前就能进行验证,那么不仅能极大降低部署时发生意外的概率,还能为性能优化提供指导。

现状

为尝试解决上述问题,我们在多个项目上进行过性能测试,使用过的方法主要分成三类。

方案 具体方式 优点 缺点
人为模拟请求 自己写代码或者使用简单的工具如httpload等去模拟用户请求进行测试 操作简单,能快速的得到cpu、mem、 load、 qps等极限值。 缺少真实用户交互行为,缺乏真实性
copy线上流量 使用tcpcopy工具实时copy线上流量到某台机器 操作简单,是真实线上请求,且对线上服务压力无影响 需要准备一套跟线上机器配置、依赖一致的独立环境,同时如果是服用线上的环境的话,一些写操作的请求被copy会有问题
线上流量切换 直接用线上的机器和环境,通过调整nginx配置参数,逐渐将要做压测的机器的权重增加,然后观察该机器各个指标性能 真实生产线流量,能把用户行为导向压测服务器,是最为真实的用户行为,能够把一些需要登陆,有用户交互行为的性能真实的反映出来 因为是用生产系统真实流量来模拟压测,无法得出最大值,如果阀值设置有误,也存在一定的风险。此外该性能测试也不能经常进行

性能测试指标

不同服务测试指标应该不同,相应的标准也不同,例如接入层服务和后端服务指标是不同的。
如果我们能为各个服务制定类似如下的标准,以后再进行性能测试就有了参考依据。
随着服务的发展,这些标准也会随之相应改动,要求会越来越严格。

判断指标 不通过的标准
超时概率 大于万分之一
错误概率 大于万分之一
平均响应时间 超过100ms
每分钟处理的请求量 小于2w
cpu使用率 平均每核超过75%
负载(load) 平均每核超过1.5

性能测试

根据压力变化模型,将性能测试分成狭义的4种类型:

注意事项

压测流程

  1. 检查硬件和中间件配置信息和运行健康状况,比如Tomcat最大连接数设置是否合理、Nginx配置是否合理等,确保它们不会影响压测结果
  2. 确定压测目标,比如“压测某HTTP接口的极限,要求1000并发用户下单台tomcat能达到5000tps”
  3. 部署应用到压测服务器,准备好发起测试的服务器(如果能和压测服务器一样最好,不能一样至少也要做到在同一个局域网内),然后用ping、traceroute查看下网络连通状况
  4. 确定压测基准,比如获取心跳检测请求的极限tps
  5. 构造尽可能接近真实用户访问情况的测试数据,比如用tcpcopy复制线上真实流量
  6. 逐渐增大并发量和总请求数,观察系统层面的各项 指标和应用运行状况,采用的工具一般是ab、jmeter、loadrunner等
  7. 有时候可能需要长时间让系统高负载运行,比如观察系统长时间处于高负载情况下是否会出现GC故障

一些经验教训

  1. 不要迷信“推荐配置”,需要根据实际情况调整配置。比如现在我们Thrift服务的selector线程数推荐值为2,worker线程数推荐值为10,然而对平均执行时间10ms左右的Thrift接口做压测时发现大量请求被阻塞,而当调整selector线程数为20、worker线程数为100后发现阻塞情况显著减轻

  2. 压测时一切判断必须基于真实测量数据,不能想当然。比如认为某个环节的逻辑很少,然后武断地认为性能瓶颈肯定不会出在那个环节,然后就忽略测量这个环节的耗时

  3. 可能不止一个环节存在性能瓶颈,比如某个请求会流经 A => B => C => D四个环节,经过测量发现当前性能瓶颈存在于A环节(比如80%的时间都消耗在A环节),然后经过努力终于把环节A的耗时降下来了,也许你会发现吞吐量和平均响应时间还是上不去并且再测量后发现现在性能瓶颈又变成C了。原因是:实际上B和C两个环节都存在性能问题,只不过未对B环节调优之前,大部分请求流量都堵塞在B环节,导致到达C环节的请求流量压力非常小,所以C环节的性能问题也就凸显不出来了;而当排除B环节的性能问题后,C环节单位时间内接收到的流量剧增,自然而然C环节的性能问题就暴露出来了。也正因此,对于复杂的业务流程,压力测试很难做到一蹴而就,需要逐一排查突破

  4. 尽可能自动化获取各个环节的性能数据。如果能通过一个集成的监控系统直观地观察到各个环节的耗时,那么对于诊断整个系统的性能瓶颈将非常有帮助(当你尝试过手动插入执行时间记录日志并收集分析后就能切身体会这点了)。同时监控系统也将为提升系统稳定性和可用性提供一大保障

  5. 即使你依赖的一个服务号称能达到tps多少多少,号称性能有多快多快,也有必要先弄清楚它的压测场景(用多少数据测的、并发用户多少、总请求多少、测试请求数据是什么样的、能否复现)。确认没问题后还要再检查自己的压测设置有没有问题,比如一个高性能HTTP接口也可能因为你的网络环境或者HTTP客户端连接池大小设置不当、超时时间设置不当等原因而达不到你想要的性能

  6. 高并发场景如果使用log4j(假如采用默认配置)打印大量日志,会对系统吞吐量造成巨大影响,因为默认log4j写日志是同步写,多线程并发写日志时会等待一个同步锁. 推荐使用logback替换log4j,或者采用异步写日志并调大log buffer size.

点击查看评论

关注公众号,接收最新消息

关注小密圈,学习各种算法

tiankonguse +
穿越