polaris1119 / golangweekly

Go语言爱好者周刊,每周日发布
https://studygolang.com/go/weekly
2.25k stars 145 forks source link

【自荐文章】4C-2G 来战 [ Golang Websocket 百万连接测试 ] #103

Closed lesismal closed 1 year ago

lesismal commented 1 year ago

4C-2G 来战 [ Golang Websocket 百万连接测试 ]

代码代码: https://github.com/lesismal/go-websocket-benchmark

使用框架: https://github.com/lesismal/nbio

概要:4cpu 核心,2G 内存,100 万连接,1k 数据载荷,500 万次 Echo 测试,TPS 10+万,详情请继续往下看。

以前发帖子遇到过很多次被人说golang搞poller、同步变回调是倒退、golang搞poller这没用那没用,所以

前置声明:

绝大多数人不需要百万级连接场景的优化,但确实有公司有项目有人需要,搞这些东西就是为了满足这些需要; 标题 4C-2G 只是作为一个参考指标,用不是特别高的配置更能体现框架的承载力。采用这个配置并不是鼓励实际场景就要用这么低的配置去处理百万连接,实际场景应从实际出发; 否定别人只需要动动嘴,但技术是实在的,如果也有兄弟姐妹想说 nbio 之类的 poller 没用,请确认自己真正了解相关知识,然后带上实际的论据观点再来讨论,如果实在想这么讲,也请先看下旧帖。 以前很多次遇到很多人先入为主地以为异步框架就是要写回调、golang 框架也如此。 为了避免误解,这里也再对 nbio 的同步异步做下简要说明: nbio 底层非阻塞、异步 io ,但使用逻辑协程池处理 http 请求、websocket 消息,由于 golang 协程不像进程线程成本那么高,所以逻辑协程池 size 比 c/cpp 或者其他语言的逻辑线程数量大得多,所以用户仍然可以写同步逻辑,实际上也是这样处理的。

为了避免既当裁判又当运动员、甚至误导用户,每当有人问我性能时,我通常是建议用户以自己实测得到的性能数据为准,而不是直接相信测试库作者提供的数据。所以建议有兴趣的兄弟姐妹在自己环境进行测试。

如果测试库代码有误,欢迎 Issue/PR 来指正更正。

在这里也邀请并欢迎大家来跑下多个 go websocket 框架的测试,并留言到这里供参考: https://github.com/lesismal/go-websocket-benchmark/issues/11

另外:除了 nbio 以外的其他 go websocket 框架多数主要是基于 golang 标准库、每个连接一个协程,这种普通配置的硬件上无法跑到海量连接,所以百万连接测试的脚本默认只针对 nbio 自己,如果想测试更多参数,请自行修改脚本。 gev 支持百万但不支持 TLS ,gobwas+netpoll 有 for loop 阻塞问题,所以目前没有添加它们,以后可能会添加。

下面是我的 ubuntu vm 上跑的数据,仅供参考

环境:

--------------------------------------------------------------
os:

Ubuntu 20.04.6 LTS \n \l

--------------------------------------------------------------
cpu model:

model name  : AMD Ryzen 7 5800H with Radeon Graphics
--------------------------------------------------------------
              total        used        free      shared  buff/cache   available
Mem:       16362568      396988    15151676        1636      813904    15656380
Swap:             0           0           0
--------------------------------------------------------------
# taskset 0-3, nbio server 只占 4 cpu 核心
run nbio_nonblocking server on cpu 0-3
--------------------------------------------------------------

压测结果:

--------------------------------------------------------------
BenchType  : Connections
Framework  : nbio_nonblocking
TPS        : 26545    # 每秒建立连接数
Min        : 20ns     # 建立单个连接最小耗时
Avg        : 74.80ms  # 建立单个连接平均耗时
Max        : 37.67s   # 建立单个连接最大耗时(实际压测并发度大,有一些容易失败,目前测试逻辑会重试、多次重试时间导致最大值时间较长)
TP50       : 30ns     # 前 50%次建立连接最大耗时
TP75       : 30ns     # 前 75%次建立连接最大耗时
TP90       : 30ns     # 前 90%次建立连接最大耗时
TP95       : 30ns     # 前 95%次建立连接最大耗时
TP99       : 31ns     # 前 99%次建立连接最大耗时
Used       : 37.67s   # 总耗时
Total      : 1000000  # 建立连接数
Success    : 1000000  # 成功建立连接数
Failed     : 0        # 建立连接成功数(实际压测并发度大,有一些容易失败,目前测试逻辑会重试、多次重试都失败才算失败)
Concurrency: 2000     # 并发度( 2000 个协程,每个协程循环建立连接)
--------------------------------------------------------------
BenchType  : BenchEcho
Framework  : nbio_nonblocking
TPS        : 113789     # 每秒 Echo 次数
Min        : 182.56us   # 单次 Echo 最小耗时
Avg        : 435.80ms   # 单次 Echo 平均耗时
Max        : 1.69s      # 单次 Echo 最大耗时
TP50       : 407.61ms   # 前 50%次 Echo 最大耗时
TP75       : 554.56ms   # 前 75%次 Echo 最大耗时
TP90       : 698.06ms   # 前 90%次 Echo 最大耗时
TP95       : 800.52ms   # 前 95%次 Echo 最大耗时
TP99       : 1.07s      # 前 99%次 Echo 最大耗时
Used       : 43.94s     # 总耗时
Total      : 5000000    # 测试 Echo 次数
Success    : 5000000    # 测试 Echo 的成功次数
Failed     : 0          # 测试 Echo 的失败次数
Conns      : 1000000    # 测试的连接数
Concurrency: 50000      # 并发度( 5w 个协程,每个协程循环取当前可用的连接进行 Echo )
Payload    : 1024       # websocket body size
CPU Min    : 95.96%     # CPU 最小值(采集开始时较小)
CPU Avg    : 347.80%    # CPU 平均值
CPU Max    : 380.94%    # CPU 最大值
MEM Min    : 1.82G      # MEM 最小值( Benchmark 开始前有进行 Warmup ,所以起始内存最低值已经较大)
MEM Avg    : 1.92G      # MEM 平均值
MEM Max    : 1.94G      # MEM 最大值

polaris1119 commented 1 year ago

已收录 https://github.com/polaris1119/golangweekly/blob/master/docs/issue-191.md