天天看點

golang主流高性能web架構性能測試

測試目的

由于K8s緣故涉獵go語言,發現golang的web架構很多,都号稱高性能标杆;之前一直緻力于c++高性能服務端架構研究,出于好奇,想單從性能層面客觀比較一下go的衆多web架構,另一方面也希望看看c++的實作與go語言實作之間究竟存在多大差異。

高性能服務架構評估名額很多,但一般來講吞吐量與QPS是關鍵考量名額,吞吐量衡量帶寬使用率,QPS主要考驗架構排程性能(幾乎所有可稱之為“高性能”的服務架構都沒有吞吐量問題,畢竟網絡瓶頸很輕易就達到了)。由于是架構本身QPS測試,為了屏蔽http協定實作差異選擇最精簡的協定頭(協定處理一般不會有鎖,為cpu密集型),是以要求請求/傳回封包盡可能小,本文測試基于http協定,傳回空封包。

為了實作測試的第二個目的,特将一個自撸的c++服務架構作為c++實作的”磚頭”,加入到對比測試中。此架構尚未開源,其高性能特性保障展現在如下設計上:

  • 跨平台實作socket多路複用,支援:poll、epoll、kqueue、port、select、IOCP等模型
  • 采用lock-free算法
  • 線程池設計
  • socket連接配接池
  • 多級任務隊列

    ……

PS:

好吧,這樣一來貌似更接近測試socket服務架構排程性能……
不要糾結keep-alive,因為wrk使用HTTP/1.1,預設都是keep-alive的
           

測試環境

golang主流高性能web架構性能測試

環境設定

ulimit -n 2000

壓測工具

wrk

由于環境限制,隻能wrk用戶端和待測試服務端在一台機器上運作

c++自研架構

  • 啟動腳本:(最大2000個并發連接配接,2個線程處理,http端口8080)

    ./proxy_server -i2000 -o2000 -w2 -x8080

  • 如有條件測試linux系統可自行下載下傳服務端(選擇對應平台的包):github.com/lazy-luo/smarGate
  • http傳回封包:
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive           
  • 壓測結果:
$wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    13.03ms    3.80ms 100.73ms   86.97%
    Req/Sec     9.43k     1.64k   39.35k    88.23%
  7509655 requests in 1.67m, 444.03MB read
  Socket errors: connect 0, read 794, write 2, timeout 0
Requests/sec:  75018.11
Transfer/sec:      4.44MB           
  • 資源占用:
    golang主流高性能web架構性能測試

go-restful架構:

  • main_go-restful.go
package main
import (
   "github.com/emicklei/go-restful"
   "net/http"
)
func main(){
    ws := new(restful.WebService)
    ws.Route(ws.GET("/").To(hello))
    restful.Add(ws)
    http.ListenAndServe(":8080",nil)
}
func hello(req *restful.Request,resp *restful.Response){
    resp.Write([]byte(""))
}           
$curl -i http://localhost:8080/
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 03:54:27 GMT
Content-Length: 0           
$wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    19.72ms   10.57ms 331.94ms   87.67%
    Req/Sec     6.52k     1.24k   23.75k    80.42%
  5180908 requests in 1.67m, 370.57MB read
  Socket errors: connect 0, read 844, write 3, timeout 0
Requests/sec:  51757.61
Transfer/sec:      3.70MB           
  • golang主流高性能web架構性能測試

go-echo架構:

  • main_go-echo.go
package main
import (
    "net/http"
    "github.com/labstack/echo"
)
func main() {
    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "")
    })
    e.Logger.Fatal(e.Start(":8080"))
}           
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/plain; charset=UTF-8
Date: Mon, 21 Oct 2019 04:09:24 GMT
Content-Length: 0           
$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    17.32ms    8.19ms 252.60ms   90.70%
    Req/Sec     7.52k     1.35k   39.96k    80.55%
  5974370 requests in 1.67m, 660.92MB read
  Socket errors: connect 0, read 431, write 67, timeout 0
Requests/sec:  59686.09
Transfer/sec:      6.60MB           
  • golang主流高性能web架構性能測試

go-iris架構:

  • main_go-iris.go
package main
import(
    "time"
    "github.com/kataras/iris"
    "github.com/kataras/iris/cache"
)
func main(){
    app := iris.New()
    app.Logger().SetLevel("error")
    app.Get("/",cache.Handler(10*time.Second),writeMarkdown)
    app.Run(iris.Addr(":8080"))
}
func writeMarkdown(ctx iris.Context){
    ctx.Markdown([]byte(""))
}           
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Date: Mon, 21 Oct 2019 04:11:59 GMT
Content-Length: 0           
$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    22.03ms    7.99ms 140.47ms   84.58%
    Req/Sec     5.79k   775.23    19.31k    80.35%
  4608572 requests in 1.67m, 505.43MB read
  Socket errors: connect 0, read 726, write 22, timeout 0
Requests/sec:  46041.23
Transfer/sec:      5.05MB           
  • golang主流高性能web架構性能測試

go-gin架構

  • main_go-gin.go
package main
import (
    "fmt"
    "net/http"
    "log"
    "github.com/julienschmidt/httprouter"
)
func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
    fmt.Fprint(w, "")
}
func main() {
    router := httprouter.New()
    router.GET("/", Index)
    log.Fatal(http.ListenAndServe(":8080", router))
}           
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 04:15:33 GMT
Content-Length: 0           
$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    16.71ms    7.72ms 268.45ms   87.79%
    Req/Sec     7.71k     1.58k   21.27k    82.12%
  6130281 requests in 1.67m, 438.47MB read
  Socket errors: connect 0, read 693, write 36, timeout 0
Requests/sec:  61243.74
Transfer/sec:      4.38MB           
  • golang主流高性能web架構性能測試

go-chi架構:

  • main_go-chi.go
package main
import (
    "net/http"
    "github.com/go-chi/chi"
)
func main() {
    r := chi.NewRouter()
    r.Get("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte(""))
    })
    http.ListenAndServe(":8080", r)
}           
$ curl -i http://localhost:8080/
HTTP/1.1 200 OK
Date: Mon, 21 Oct 2019 04:18:42 GMT
Content-Length: 0           
$ wrk -d 100s -c 1024 -t 8 http://localhost:8080/
Running 2m test @ http://localhost:8080/
  8 threads and 1024 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    17.17ms    8.47ms 253.47ms   90.07%
    Req/Sec     7.65k     1.42k   26.08k    79.76%
  6071695 requests in 1.67m, 434.28MB read
  Socket errors: connect 0, read 110, write 2, timeout 0
Requests/sec:  60658.49
Transfer/sec:      4.34MB           
  • golang主流高性能web架構性能測試

結論:

- cpu-free mem-usage qps
c++ 15%-20% 6M 75018.11
go-gin 0%-1.5% 28M 61243.74
go-chi 0%-1% 60658.49
go-echo 0%-0.5% 59686.09
go-restful 34M 51757.61
go-iris 37M 46041.23
  • go語言web架構中gin、chi、echo性能相當,gin略顯優勢,iris實測效果不佳;
  • go語言與c++語言網絡架構比較還是存在一定性能差距,但不是決定性的;
  • go語言整體資源耗用大,c++足夠輕量高效;
  • go語言真的很易用且簡潔!!就是三方依賴太多 ,拿來主義,問題排查那是相當酸爽...... 當然,随着依賴包更新你會一直爽 :)

繼續閱讀