本系列文章索引《響應式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比較多的狀況下,效果會更加驚人。