Go語言項目(kingshard)性能優化實例剖析

kingshard性能優化網絡篇

最近kingshard的功能開發節奏慢了許多。一方面是工做確實比較忙,另外一方面是我以爲kingshard的功能已經比較完善了,下一步的開發重點應該是性能優化。畢竟做爲一個MySQL proxy,若是轉發SQL的性能不好,再多的功能都無濟於事。因此這個週末一直宅在家裏優化kingshard的轉發性能。通過兩天的探索發現,將kingshard的轉發SQL性能提高了18%左右,在這個過程當中學到了一下知識。藉此機會分享一下,同時也是督促一下本身寫博客的積極性。:)mysql

1. 發現kingshard的性能瓶頸

首選,對kingshard進行性能優化,咱們必需要找到kingshard的性能瓶頸在哪裏。Go語言在性能優化支持方面作的很是好,藉助於go語言的pprof工具,咱們能夠經過簡單的幾個步驟,就能獲得kingshard在轉發SQL請求時的各個函數耗時狀況。git

1.1 環境搭建

根據kingshard使用指南搭建一個kingshard代理環境。我是用macbook搭建的環境,硬件參數以下所示:github

CPU: 2.2GHZ * 4
內存:16GB
硬盤: 256GB

1.2 性能測試步驟

具體步驟以下所述:算法

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
  • 按照上述步驟測試三次(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.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的最新消息與後端架構設計類的文章,都會在這個公衆號分享。圖片描述

相關文章
相關標籤/搜索