大促准备(五)压测改造
压测是准备大促过程中至关重要的一个环节,在真正开始压测之前系统通常要做一定的改造,以使得压测请求的代码执行路径更符合实际情况,主要进行的改造和准备主要有如下内容
1、存储准备
对于压测服务中涉及到db(msyql、hbase、ob)的系统,在压测前需要联系DBA、PE先准备好所需的压测表。
对于缓存(tair、tbase)也需要进行压测缓存key和正式key区隔处理,可以和zcache同学确认其是否支持,如果不支持,就需要自己实现。另外缓存中压测数据的过期时间可以设置的短些,能够满足压测的要求即可,以免得压测数据占用过多的缓存空间,影响正常业务的缓存命中率(最好能通过drm推送的方式来修改)。
2.异步线程传递context
在很多系统中会使用线程池来执行异步操作或者是并行执行操作,而当前请求是否为压测请求的标识是在ThreadLocal中保存的,具体到sofa系统中是用AbstractLogContext来封装实现的。因而在进入到异步线程中时需要把当前请求的context传入到异步线程中,并且在异步线程中的执行中添加try finally语句块,在finally中需要把异步线程中context清除掉,以免线程池下次执行时造成context 污染。
3.缓存命中率改造
在进行压测时,所使用的压测数据是有限的,百万级别的就算是比较大了,而压测的请求量通常是每秒数万或数十万的量,因而会重复使用这些数据。对于会访问缓存的请求,当循环一轮后这些数据基本上都会在缓存中了,如果此时仍然持续压测,那基本上就只是压缓存了,而不能压到db操作和后续的do转model等操作了。
因而应当能够控制一定比例的请求的强制走db,这个比例值应当是可以动态调整的,通过调整这个比例也可以了解自己系统db的qps峰值、自己系统全部走db情况下服务的qps值。
4.逻辑改造
缓存命中率改造主要是针对读服务,目的是使得压测请求执行情况尽量符合真实情况。对于写服务也需要做类似的改造。
大多数的写服务会进行幂等控制,会根据主键先到db中进行下查询,如果查询到数据,就不再写入db了,因而在进行写服务压测时,也需要进行适当的改造,以使得请求更符合真实情况,主要的改造有两种方式:
- 主键数据足够的随机,避免发生重复,这样可以保证每次的数据都会写db
- 对于主键有一定规则要求,不能通过随机数mock的,针对压测流量,当db中已存在数据,执行一次update操作,修改一个不关键的属性,比如更新时间等,也执行下db写操作
5.链路切换改造
在大促中还有一种情况是大促时执行的链路和日常的链路是不同的,对于链路的切换也需要添加对应的控制,能够通过推送配置进行切换。
更精确的控制的是压测时进行的链路切换只针对压测请求生效而不对正常请求生效,在大促期间的链路切换对日常请求生效。要实现这样的控制,在代码的实现层面需要好好的设计,一方面要满足功能的实现,一方面还要具备良好的可读性,减少后续的维护成本。
6.数据|请求录制
前面提到的都是正常的压测,这些压测所采用的数据都是通过一定的规则mock出来的,但是对于有些特殊的场景,是不能用随意mock出来的数据的,这时就必须把线上已有的数据或者请求录制起来,通过重放的形式进行压测。
这种情况会变得特别复杂,需要开发特别的系统或者对已有的中间件进行改造才可以实现。