最近kingshard的功能開發節奏慢了許多。一方面是工做確實比較忙,另外一方面是我以爲kingshard的功能已經比較完善了,下一步的開發重點應該是性能優化。畢竟做爲一個MySQL proxy,若是轉發SQL的性能不好,再多的功能都無濟於事。因此這個週末一直宅在家裏優化kingshard的轉發性能。通過兩天的探索發現,將kingshard的轉發SQL性能提高了18%左右,在這個過程當中學到了一下知識。藉此機會分享一下,同時也是督促一下本身寫博客的積極性。:)mysql
首選,對kingshard進行性能優化,咱們必需要找到kingshard的性能瓶頸在哪裏。Go語言在性能優化支持方面作的很是好,藉助於go語言的pprof工具,咱們能夠經過簡單的幾個步驟,就能獲得kingshard在轉發SQL請求時的各個函數耗時狀況。git
根據kingshard使用指南搭建一個kingshard代理環境。我是用macbook搭建的環境,硬件參數以下所示:github
CPU: 2.2GHZ * 4 內存:16GB 硬盤: 256GB
具體步驟以下所述:算法
1.獲取一個性能分析的封裝庫sql
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.37ms Threads fairness: events (avg/stddev): 10004.4375/24.95 execution time (avg/stddev): 9.6530/0.00
7.將cpu.prof拷貝到bin/kingshard所在位置
8.調用go tool工具製做CPU耗時的PDF文檔
go tool pprof -pdf ./kingshard cpu.pprof > report.pdf
經過上述命令,能夠生成壓測期間主要函數耗時狀況。從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選項,來達到每一個數據包傳輸儘可能多的數據,減小系統調用的目的。
發現了性能瓶頸之後,修改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.13ms Threads 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/king...
歡迎關注後端技術快訊公衆號,有關kingshard的最新消息與後端架構設計類的文章,都會在這個公衆號分享。