扩容机器时需要注意什么?
数据库连接:某服务集群一共有 10 个容器实例,每个实例会建立约 100 个数据库连接,加起来就是约 1000 个连接,假设数据库总共支持的连接数为 1200 个,这是能够支撑现状的。但如果考虑到近期业务增长较快,会导致服务负载较大,需要扩容 5 个实例,那么总的数据库连接数大约会达到 1500 个,这就肯定支撑不住的,所以对服务进行扩容时,对数据库也需要同步扩容。
扩容机器时容易忽略的地方?
系统有四个服务 A、B、C、D,A 调用 B,B 调用 C 和 D。其中,A、B、D 服务是系统的核心服务(像是电商系统中的订单服务、支付服务等等),C 是非核心服务(像评论服务、审核服务)。
作为入口的 A 流量增加,你可能会考虑把 A、B 和 D 服务扩容,忽略 C。
C 就有可能因为无法承担这么大的流量,导致请求处理缓慢,进一步会让 B 在调用 C 的时候,B 中的请求被阻塞,等待 C 返回响应结果。这样一来,B 服务中被占用的线程资源就不能释放。
B 就会因为线程资源被占满,无法处理后续的请求。那么从 A 发往 B 的请求,就会被放入 B 服务线程池的队列中,然后 A 调用 B 响应时间变长,进而拖垮 A 服务。
响应时间看平均值还是看分位线?
一个服务的常态响应时间为 100ms,可接受的最大响应时间为 150ms,当服务负载升高至接近瓶颈时,有约 20% 的请求响应时间增加了一倍达到 200ms,也就是说大约有 20% 的用户有可能已经受到影响。
假设有100个请求:
平均值是多少?
(80×100ms + 20×200ms) / 100=120ms
分位线TP95是多少?
200ms
平均值很容易“冲淡”一些耗时较长的请求,导致容量问题被掩盖。以分位线作为响应时间关注点的本质在于,尽管只是小部分请求的响应时间增长,但服务容量已经处于不充足的萌芽状态了,这时候如果不加干预,很有可能服务容量会迅速恶化。
另外,虽然这个问题是针对响应时间的,但其实可以推广到很多地方,比如数据库的读写耗时、缓存的读取耗时等等,都应当关注分位线。
TP99分位线一直很低是好事情吗?
测试数据存在问题,导致对该被测服务的测试请求始终会走入异常分支,主体的业务逻辑都没有经过,响应时间当然就短了。
服务本身的状态码设置也有问题,无论请求正常还是异常,一律都返回了 200。
响应时间越短越好,是建立在场景正确、服务无异常的基础上的。
对线上压测应用服务需要怎么改造?
绕开限制逻辑:比如系统针对短时间内反复下单的用户将进行限制,这个逻辑针对压测流量需要放开。
数据隔离前置:数据隔离前置能够减轻其他应用服务改造的工作量,比如大数据报表中需要对压测数据进行剔除,如果这些报表的数据源都在数据仓库里,那么我们完全可以在压测数据生成时就隔离掉不进数据仓库,这样大数据服务就无需改造了。
Mock 逻辑:有些对外交互的服务是不太方便发起大量真实请求的,比如支付和清结算等,这些功能可以在识别到压测流量后走 Mock 服务,也就是模拟一个正常的返回,而不是直接调用真实服务。
垃圾回收器怎么选?
追求响应时间:
堆内存能够给到 8G 以上的,建议选择 G1;
堆内存较小或 JDK 版本较低的,可以选择 CMS;
追求吞吐量:
建议选择 ParallelGC;
这也是 JDK8 的默认垃圾回收器;
参考资料:
https://time.geekbang.org/column/article/375806?cid=100078501
----END----
这里记录,我每周碰到的,或想到的,引起触动,或感动的,事物的思考及笔记。不见得都对,但开始思考记录总是好的。