golang主流高性能web框架性能测试

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: 测试目的由于K8s缘故涉猎go语言,发现golang的web框架很多,都号称高性能标杆;之前一直致力于c++高性能服务端框架研究,出于好奇,想单从性能层面客观比较一下go的众多web框架,另一方面也希望看看c++的实现与go语言实现之间究竟存在多大差异。

测试目的

由于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的

测试环境

env

环境设置

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
  • 资源占用:
    proxy_server

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(""))
}
  • http返回报文:
$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
  • 资源占用:
    go_restful

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"))
}
  • http返回报文:
$ 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
  • 资源占用:
    go_echo

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(""))
}
  • http返回报文:
$ 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
  • 资源占用:
    go_iris

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))
}
  • http返回报文:
$ 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
  • 资源占用:
    go_gin

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)
}
  • http返回报文:
$ 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
  • 资源占用:
    go_chi

结论:

- cpu-free mem-usage qps
c++ 15%-20% 6M 75018.11
go-gin 0%-1.5% 28M 61243.74
go-chi 0%-1% 28M 60658.49
go-echo 0%-0.5% 28M 59686.09
go-restful 0%-0.5% 34M 51757.61
go-iris 0%-1% 37M 46041.23
  • go语言web框架中gin、chi、echo性能相当,gin略显优势,iris实测效果不佳;
  • go语言与c++语言网络框架比较还是存在一定性能差距,但不是决定性的;
  • go语言整体资源耗用大,c++足够轻量高效;
  • go语言真的很易用且简洁!!就是三方依赖太多 ,拿来主义,问题排查那是相当酸爽...... 当然,随着依赖包升级你会一直爽 :)
相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
目录
相关文章
|
1月前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
42 4
|
1月前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
100 3
|
16天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
103 45
|
11天前
|
缓存 前端开发 中间件
go语言中Web框架
【10月更文挑战第22天】
20 4
|
11天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP是一种流行的服务器端脚本语言,自诞生以来在Web开发领域占据重要地位。从简单的网页脚本到支持面向对象编程的现代语言,PHP经历了多次重大更新。本文探讨PHP的现代演进历程,重点介绍其在Web开发中的应用及框架创新,如Laravel、Symfony等。这些框架不仅简化了开发流程,还提高了开发效率和安全性。
19 3
|
11天前
|
前端开发 JavaScript 开发工具
从框架到现代Web开发实践
从框架到现代Web开发实践
21 1
|
14天前
|
SQL 安全 PHP
探索PHP的现代演进:从Web开发到框架创新
PHP 自发布以来一直在 Web 开发领域占据重要地位,历经多次重大更新,从简单的脚本语言进化为支持面向对象编程的现代语言。本文探讨 PHP 的演进历程,重点介绍其在 Web 开发中的应用及框架创新。自 PHP 5.3 引入命名空间后,PHP 迈向了面向对象编程时代;PHP 7 通过优化内核大幅提升性能;PHP 8 更是带来了属性、刚性类型等新特性。
24 3
|
17天前
|
前端开发 JavaScript
Bootstrap Web 前端 UI 框架
Bootstrap 是快速开发 Web 应用程序的前端工具包。
30 3
|
17天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
29 2
|
1月前
|
前端开发 JavaScript UED
构建现代Web应用:使用React框架打造单页面应用
【10月更文挑战第9天】构建现代Web应用:使用React框架打造单页面应用