稳定性思考-强弱依赖2

本文涉及的产品
性能测试 PTS,5000VUM额度
注册配置 MSE Nacos/ZooKeeper,118元/月
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
简介: 弱依赖“并发请求数阀值”这个值设置多少合适?     “并发请求数阀值”在大部分情况下可以理解为同时工作的线程数阀值,这个值不是越大越好,也不是越小越好,而是在最高QPS输出的情况下这个值越小越好。这个也是系统性能优化的一个方向,高QPS,少线程。     线程它是驱动业务逻辑执行的载体,在执行
弱依赖“并发请求数阀值”这个值设置多少合适?
    “并发请求数阀值”在大部分情况下可以理解为同时工作的线程数阀值,这个值不是越大越好,也不是越小越好,而是在最高QPS输出的情况下这个值越小越好。这个也是系统性能优化的一个方向,高QPS,少线程。
    线程它是驱动业务逻辑执行的载体,在执行逻辑的生命周期中,它会申请各种各样的资源,会占有CPU,会申请内存对象并持有,会申请锁并持有,会申请IO资源并持有,然后再完成一些工作之后,在恰当的时间释放这些资源。如果这个生命周期越长,那么直接导致这些资源被持有的时间越长。导致资源的竞争更加厉害。在java应用中,一个明显的场景就是由于内存申请之后长时间不能释放,导致FULLgC非常频繁。
    另一个角度,因为响应时间变长之后,会直接导致需要更多的线程数来满足不变的QPS,由于线程越多,导致对资源的持有和竞争更加激烈,表现CPU占用很高,Load很高,这是一个恶性循环,需要打破这个环。
    以cache访问为例
    假设客户端app(相对cache而言)本身的输入QPS为200(平均每秒有100个用户请求到此系统),每次业务请求会调用2次Cache,相当于对cache请求的QPS是200*2=400,也就是说如果要满足客户端app 200的qps,那么需要客户端app对Cache有400qps的访问能力,假设客户端app访问cache的平均响应时间为1ms。

    用户--1次请求-->[APP]--2次请求-->[Cache]
根据公式:QPS=1000ms/RT(平均响应时间) * threadNum(并行线程数)
threadNum=QPS/1000 * RT = 400/1000 * 1
                    = 1
Cache响应时间为1ms,那么只需要一个线程就足以提供每秒400次的请求服务,其实理论上1个线程可以提供1000的qps,当然前提条件是cacheServer有非常高的吞吐容量
        我们模拟一下故障
        此时CacheServer发生了故障,对CacheServer的调用全部超时,响应时间变成了3000ms
根据公式计算:threadNum=QPS/1000 * RT = 400/1000 * 3000 =1200
此时需要1200个线程才能满足400QPS的流量 ,换而言之就是客户端会有1200个线程堵塞在CacheServer的访问请求上。这个线程数量早就超过了客户端配置的线程数量,app系统表现为hung住,几乎不能处理任何用户的请求,如果客户端配置的线程数是200,那么根据之前对detail,hesper等java应用系统的压测,200个app线程,会导致系统频繁的发生FullGC(原因是线程数量多,每个线程执行的时间长),此时app的实际QPS反而会比系统极限QPS低很多。
对于APP来说,此时应该是减少对cache的访问量,让少量的线程去试探是否恢复,而不是所有线程都堵塞在这里,原则上来说不管对什么资源的访问,都不能出现大量线程堵塞的情况。
最佳的做法是,限制对cache访问请求的线程数量。比如限制为10: 此时我们再来看一下上面的故障
此时APP的qps仍然为200(假设用户流量不会发生变化),那么可以计算得到app对CacheServer访问的qps变为3:QPS=1000ms/RT(平均响应时间) * threadNum(并行线程数)=1000/3000 * 10 = 3。由于APP只是堵塞了10个线程,超过10个请求后会直接return,并做好return之后相关逻辑处理。app本身并没有因为大量线程消耗大量的资源,app的状态依旧正常,只是cache不能命中。
        接下去故障恢复
        由于用户对APP的请求没有堆积,堵塞在访问cache的线程会因为超时设置,导致每隔3秒会有一个堆积请求退出,同时会放入新的线程,一旦cacheserver恢复,即便是1个线程理论上都可以提供1000的qps,所以系统会非常快速的恢复。
从结果上来看,“超时设置”策略是一种对每一个请求都会起作用的策略,而“并发请求阀值限制”策略是对一段时间持续发生系统变慢后才起作用。系统都正常的情况下超时设置会有一定的误杀,但是异常情况下由于超时的设置还是会导致一定线程的堵塞,所以“超时设置”加上“并发请求阀值设置”是一个很好的降级,流控策略,比单独使用一种有更好的效果。
        另外阀值为什么是10,不是20,不是100,关于这个值到底是多少?可以通过计算得到
        还是400QPS为例,对于客户端来说需要提供一个数据:你可以接受cache的响应时间是多少,平均响应时间为1ms,假设我们可以接受的是10ms:
QPS=1000ms/RT(平均响应时间) * threadNum(并行线程数)
threadNum = 400 * 10 / 1000 = 4
4个线程,没错是4个,不过设置4个线程阀值还是太小
如果是接受100ms:
threadNum = 400 * 100 / 1000 = 40
        一般建议设置40个,40个线程阀值的效果等同于设置100ms超时时间。
 另外,对于客户端APP来说可以接受堵塞多少线程?根据性能压测经验,一般平均50ms左右响应时间的java-APP,最好不要超过60,平均响应时间100ms的最好不要超过100。这个值是相对的,和系统有关系,特别是和系统单次请求所需内存开销,响应时间变化有关。
        再谈一下系统的响应时间
        正常情况RT这个值说应该是一个相对固定的值,因为代码的逻辑是一样的,干活的量也是一样的,好比一个卖票的窗口,卖一张票所需要的时间是固定的。那为什么有时候我们买票需要花更多的时间呢?原因是由于需求的QPS大于供给的QPS,我们被进入了排队,我们的时间消耗在了排队和资源争夺。而且一旦这个条件持续满足“需求的QPS大于供给的QPS”,响应时间会越来越慢,慢到无穷的大。
在系统做性能压测的情况下响应时间的曲线一般是这样的:
                                 /
__________________/    x轴压测用户数,y轴响应时间
        虽然响应时间变长,但是QPS不会变高,反而会下降,系统的极限QPS是由系统的瓶颈资源的极限QPS决定的,因为瓶颈资源的极限QPS几乎是一个固定的值,所以决定了系统只有一个最高QPS,听起来好像很奇怪,因为这个值并不会因为系统补充了其他资源而变的更高,有时候有人会认为我增加线程数量,是不是会增加这个最高QPS,答案肯定是不一定的。
相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
4月前
|
测试技术
质量标准化实践问题之确保项目进度和质量受控如何解决
质量标准化实践问题之确保项目进度和质量受控如何解决
38 2
|
5月前
软件复用问题之度量组件的可靠性,如何解决
软件复用问题之度量组件的可靠性,如何解决
|
5月前
软件复用问题之如果无法进行定量分析,评估系统的复用性要如何解决
软件复用问题之如果无法进行定量分析,评估系统的复用性要如何解决
|
4月前
|
测试技术
软件交付质量问题之对于处理质量与成本的平衡该如何实现
软件交付质量问题之对于处理质量与成本的平衡该如何实现
|
5月前
|
设计模式 存储 Java
代码优化设计问题之解耦策略路由和策略实现的依赖问题如何解决
代码优化设计问题之解耦策略路由和策略实现的依赖问题如何解决
|
7月前
|
算法
【核心复现】同时考虑考虑孤岛与重构的配电网故障恢复运行策略
【核心复现】同时考虑考虑孤岛与重构的配电网故障恢复运行策略
|
7月前
软件体系结构 - 可靠性指标
软件体系结构 - 可靠性指标
344 0
软件体系结构 - 可靠性指标
|
运维 程序员 测试技术
如何保证项目质量?层层卡点,一次把事情做对!
如何保证项目质量?层层卡点,一次把事情做对!
193 0
|
7月前
|
安全 测试技术 持续交付
如何保证被测产品的质量
如何保证被测产品的质量
|
7月前
|
开发框架 监控 测试技术
产品迭代过程中如何保证产品质量的稳定性
产品迭代过程中如何保证产品质量的稳定性