本系列文章索引《响应式Spring的道法术器》
前情提要 Spring WebFlux快速上手 | Spring WebFlux性能测试 | Spring WebClient性能测试
本文源码react
许多数据库已陆续推出官方的异步驱动,在Spring Data Reactive中,已经集成了Mongo、Casandra、Redis、CouchDB的异步驱动。git
在Spring WebFlux中使用 Reactive Mongo的示例见Spring WebFlux快速上手。github
这一节咱们经过使用YSCB对MongoDB的同步和异步驱动的性能基准测试,来观察异步驱动的优点。mongodb
YCSB(Yahoo! Cloud Serving Benchmark)是雅虎开源的一款用于测试各种云服务/NoSQL/键值对存储的性能基准测试工具。YCSB很赞,使用起来很简单,咱们就按照wiki介绍来操做便可。shell
1)准备YCSB数据库
若是使用Windows,请参考这里来预先安装必要的软件和工具。bash
获取YCSB有两种方式,一种是直接下载压缩包:网络
curl -O --location https://github.com/brianfrankcooper/YCSB/releases/download/0.12.0/ycsb-0.12.0.tar.gz tar xfvz ycsb-0.12.0.tar.gz cd ycsb-0.12.0
另外一种是基于源码构建:session
git clone git://github.com/brianfrankcooper/YCSB.git cd YCSB mvn clean package
此时就可使用bin/ycsb
命令来进行性能测试了,运行一下:多线程
usage: bin/ycsb command databse [options] Commands: load Execute the load phase run Execute the transaction phase shell Interactive mode ...
从上边的命令帮助能够看到,咱们能够运行三种命令:
本节的测试主要用到load和run来进行数据的批量操做,先用load命令加载数据集,而后使用run命令测试数据操做。在YCSB中,测试的工做量由workload文件来定义。咱们看到在workloads
下有workload[a-f]几个配置文件,好比workloada:
# Yahoo! Cloud System Benchmark # Workload A: Update heavy workload # Application example: Session store recording recent actions # # Read/update ratio: 50/50 # Default data size: 1 KB records (10 fields, 100 bytes each, plus key) # Request distribution: zipfian recordcount=1000 operationcount=1000 workload=com.yahoo.ycsb.workloads.CoreWorkload readallfields=true readproportion=0.5 updateproportion=0.5 scanproportion=0 insertproportion=0 requestdistribution=zipfian
可见配置文件定义了记录条数、操做次数、以及不一样的操做所占的百分比。好比上边readproportion
和updateproportion
都是50%,从注释也能够看出来,这模拟的是一种更新操做比较频繁的场景,能够模拟Web应用中保存session的场景。
几个workload的配置经过不一样的read/update/scan/insert操做比例来模拟不一样的场景。
咱们能够经过以下命令对mongo运行基于workloada的load阶段的性能测试:
bin/ycsb load mongodb -P workloads/workloada
默认是链接localhost:27017
的mongodb数据库,若是但愿指定数据库链接信息,能够用-p参数指定:
bin/ycsb load mongodb -P workloads/workloada \ -p "mongodb.url=mongodb://192.168.0.101:27017/ycsb?w=1&maxPoolSize=32&waitQueueMultiple=20"
同时还指定了链接池最大数量和最多等待数量。
固然咱们也能够经过命令参数覆盖workloada文件中的数值,好比:
bin/ycsb load mongodb -P workloads/workloada \ -p "mongodb.url=mongodb://192.168.0.101/ycsb?w=1&maxPoolSize=32&waitQueueMultiple=20" \ -p recordcount=10000 -p operationcount=10000 -threads 20
此外,还用-threads
指定了并发线程数为20。
以上这些是本次测试会用到的内容,其余更多关于YCSB的使用请参考wiki吧。
2)准备测试
本次测试的目标是对比Mongodb同步和异步驱动的性能,简单起见,从吞吐量和平均操做时长两个数据来衡量。纵向上,
链接数的变化能够经过mongostat
命令来观察,以下图所示:
上边运行的
mongo-benchmark.sh
是基于bin/ycsb
命令编写的方便测试的脚本,并输出一些汇总数据(包括吞吐量和平局操做时长)方便查看,同时也会将每次bin/ycsb
命令输出的详细内容保存到output
目录下的文件中。
脚本能够在代码库中找到,若是mongo运行于localhost:27017
,可直接用以下命令执行(在与bin
同目录下):curl https://raw.githubusercontent.com/get-set/get-reactive/master/ycsb-mongo-shell/mongo-benchmark.sh | bash
图中上方是对同步驱动和异步驱动各自跑了一次基于workloada的load和run的测试,下方是mongostat
的输出(每秒输出一行),从insert
、query
、update
的数字能够找出四个橘×××的框标出的4个阶段。经过这些数据咱们能够分析出:
insert
的数字增多,加起来是测试预设的30000条数据;相似的run主要是进行基于workload的操做测试,workloada是50/50的read/update,在mongostat的输出中也有体现。conn
列能够看到数据库链接个数的变化,对于同步的驱动来讲,链接个数会从4个增长到25个,而对于异步的驱动来讲,链接个数会从4个增长到7个。经过这种方式,针对不一样的线程数,观察两种驱动的性能数据并经过mongostat的数据记录链接数。
1、不限制链接数
为了观察链接数的变化,先不限制maxPoolSize
(注释脚本中MAX_POOL_SIZE=8
那一行)。最终结果以下:
图中,每种颜色的左列和右列分别是同步和异步的数据。直观起见,咱们经过图表来对比一下:
首先对比一下load阶段和run阶段的吞吐量(柱越高越好)
能够发现,当线程数达到8个以后,吞吐量的增加趋势基本消失了,尤为是同步驱动的吞吐量还会随线程数的继续增长而略有降低。不知是否跟测试环境为四核八线程的CPU有关系。
而后对比一下INSERT、READ和UPDATE操做的平均时长(柱越低越好)
相对来讲,异步驱动能带来更快的读写操做,尤为是应对愈来愈多的线程的时候。
最后对比一下链接数
链接数的对比更加明显:对于同步的状况,链接数=线程数+5;而对于异步的状况,链接数几乎一直保持在7个。没有对比就没有伤害呀。
2、限制链接数
下面,将链接数限制为32个,测试一下线程数从30-80的状况下,同步驱动的性能数据:
经过图表对比:
可见,限制链接数以后,略有改善,可是相比异步驱动来讲,仍然有必定差距。
3)结论
首先,须要说明的是,以上并不是是以数据库调优为目的的测试,这里咱们只测试了workloada(若是你感兴趣能够将脚本中的WORKLOAD
变量修改一下,而后测试其余场景),并且限制链接数为32并无特别的依据,对测试的机器来讲,32也并不是最优的链接数。
经过本节的测试,针对MongoDB驱动咱们能够得出如下两个结论:
上边咱们分别针对Http服务端、Http客户端以及数据库进行了同步和异步的测试对比,综上来看,基于异步非阻塞的响应式应用或驱动可以以少许且固定的线程应对高并发的请求或调用,对于存在阻塞的场景,可以比多线程的并发方案提供更高的性能。
响应式和非阻塞并非总能让应用跑的更快,何况将代码构建为非阻塞的执行方式自己还会带来少许的成本。可是在相似于WEB应用这样的高并发、少计算且I/O密集的应用中,响应式和非阻塞每每可以发挥出价值。尤为是微服务应用中,网络I/O比较多的状况下,效果会更加惊人。