這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
kingshard效能最佳化網路篇
最近kingshard的功能開發節奏慢了許多。一方面是工作確實比較忙,另一方面是我覺得kingshard的功能已經比較完善了,下一步的開發重點應該是效能最佳化。畢竟作為一個MySQL proxy,如果轉寄SQL的效能很差,再多的功能都無濟於事。所以這個周末一直宅在家裡最佳化kingshard的轉寄效能。經過兩天的探索發現,將kingshard的轉寄SQL效能提升了18%左右,在這個過程中學到了一下知識。藉此機會分享一下,同時也是督促一下自己寫部落格的積極性。:)
1. 發現kingshard的效能瓶頸
首選,對kingshard進行效能最佳化,我們必須要找到kingshard的效能瓶頸在哪裡。Go語言在效能最佳化支援方面做的非常好,藉助於go語言的pprof工具,我們可以通過簡單的幾個步驟,就能得到kingshard在轉寄SQL請求時的各個函數耗時情況。
1.1 環境搭建
根據kingshard使用指南搭建一個kingshard代理環境。我是用macbook搭建的環境,硬體參數如下所示:
CPU: 2.2GHZ * 4記憶體:16GB硬碟: 256GB
1.2 效能測試步驟
具體步驟如下所述:
1.擷取一個效能分析的封裝庫
go get github.com/davecheney/profile
2.在工程內import這個組件
3.在kingshard/cmd/kingshard/main.go的main函數開始部分添加CPU監控的啟動和停止入口
func main() { defer profile.Start(profile.CPUProfile).Stop() fmt.Print(banner) runtime.GOMAXPROCS(runtime.NumCPU()) flag.Parse() ....}
4.重新編譯工程, 運行kingshard
./bin/kingshard -config=etc/ks.yaml
5.kingshard啟動後會在終端輸出下面一段提示:
2015/10/31 10:28:06 profile: cpu profiling enabled, /var/folders/4q/zzb55sfj377b6vdyz2brt6sc0000gn/T/profile205276958/cpu.pprof
後面的路徑就是pprof效能分析檔案的位置,Ctrl+C中斷伺服器
6.這時候用sysbench對kingshard進行壓力測試,得到QPS(有關sysbench的安裝和使用,請自行Google解決)。具體的代碼如下所示:
sysbench --test=oltp --num-threads=16 --max-requests=160000 --oltp-test-mode=nontrx --db-driver=mysql --mysql-db=kingshard --mysql-host=127.0.0.1 --mysql-port=9696 --mysql-table-engine=innodb --oltp-table-size=10000 --mysql-user=kingshard --mysql-password=kingshard --oltp-nontrx-mode=select --db-ps-mode=disable run
得到如下結果:
OLTP test statistics: queries performed: read: 160071 write: 0 other: 0 total: 160071 transactions: 160071 (16552.58 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 160071 (16552.58 per sec.) other operations: 0 (0.00 per sec.)Test execution summary: total time: 9.6705s total number of events: 160071 total time taken by event execution: 154.4474 per-request statistics: min: 0.29ms avg: 0.96ms max: 14.17ms approx. 95 percentile: 1.37msThreads fairness: events (avg/stddev): 10004.4375/24.95 execution time (avg/stddev): 9.6530/0.00
按照上述步驟測試三次(16552.58,16769.72,16550.16)取平均值,得到最佳化前kingshard的QPS是:16624.15
按照上述步驟,直連MySQL。測試直連MySQL的QPS,同樣測試三次QPS(27730.90,28499.05,27119.20),得到直連MySQL的QPS是:27783.05。
從上述資料可以計算出kingshard轉寄SQL的效能是直連MySQL的59%左右。
7.將cpu.prof拷貝到bin/kingshard所在位置
8.調用go tool工具製作CPU耗時的PDF文檔
go tool pprof -pdf ./kingshard cpu.pprof > report.pdf
2. 效能測試報告分析
通過上述命令,可以產生壓測期間主要函數耗時情況。從report來看,主要的耗時在TCP層資料包的收發上面。那我們應該主要考慮如何最佳化TCP層資料的收發方面。最佳化TCP傳輸效率,我首先想到了減少系統調用,每個資料包傳輸盡量多的資料。
在通過 TCP socket 進行通訊時,資料都拆分成了資料區塊,這樣它們就可以封裝到給定串連的 TCP payload(指 TCP 資料包中的有效負荷)中了。TCP payload 的大小取決於幾個因素(例如最大報文長度和路徑),但是這些因素在串連發起時都是已知的。為了達到最好的效能,我們的目標是使用儘可能多的可用資料來填充每個報文。當沒有足夠的資料來填充 payload 時(也稱為最大報文段長度(maximum segment size) 或 MSS),TCP 就會採用 Nagle 演算法自動將一些小的緩衝區串連到一個報文段中。這樣可以通過最小化所發送的報文的數量來提高應用程式的效率,並減輕整體的網路擁塞問題。
由於這種演算法對資料進行合并,試圖構成一個完整的 TCP 報文段,因此它會引入一些延時。但是這種演算法可以最小化線上路上發送的報文的數量,因此可以最小化網路擁塞的問題。但是在需要最小化傳輸延時的情況中,GO語言中Sockets API 可以提供一種解決方案。就是通過:
func (c *TCPConn) SetNoDelay(noDelay bool) error
這個函數在Go中預設情況下,是設定為true,也就是未開啟延遲選項。我們需要將其設定為false選項,來達到每個資料包傳輸盡量多的資料,減少系統調用的目的。
2.1 代碼修改和效能測試
發現了效能瓶頸以後,修改proxy/server/server.go檔案中的newClientConn函數和backend/backend_conn.go中的ReConnect函數,分別設定client與kingshard之間的串連和kingshard到MySQL之間的串連為最小化傳輸延時。具體的代碼修改可以查看這個commit。
修改後我們利用sysbench重新測試,測試命令和上述測試一致。得到的結果如下所示:
OLTP test statistics: queries performed: read: 160174 write: 0 other: 0 total: 160174 transactions: 160174 (21291.68 per sec.) deadlocks: 0 (0.00 per sec.) read/write requests: 160174 (21291.68 per sec.) other operations: 0 (0.00 per sec.)Test execution summary: total time: 7.5228s total number of events: 160174 total time taken by event execution: 119.9655 per-request statistics: min: 0.26ms avg: 0.75ms max: 10.78ms approx. 95 percentile: 1.13msThreads fairness: events (avg/stddev): 10010.8750/38.65 execution time (avg/stddev): 7.4978/0.00
測試三次得到的QPS為:21291.68,21670.85,21463.44。 相當於直連MySQL效能的77%左右,通過這個最佳化效能提升了18%左右。
總結
通過這篇文章,介紹了通過Go語言提供的pprof對kingshard進行效能分析的詳細步驟。對於其他Go語言項目也可以通過類似步驟產生效能報告文檔。效能最佳化的關鍵是發現效能瓶頸,再去找最佳化方案。有時候簡單的最佳化,就可以達到預想不到的效果,希望本文能給Go開發人員在效能最佳化方面提供一個思路。最後打個廣告:kingshard作為一個支援sharding的開源MySQL中介軟體項目,目前已經比較穩定了,且經過效能最佳化後,轉寄SQL的效能提升了不少。後續我還會在鎖和記憶體方面對kingshard進行最佳化,敬請期待。
github: https://github.com/flike/kingshard