Golang Websocket包测试指南
Golang Websocket包测试指南 我花了一个周末的时间编写了一个WebSocket库,但没想到它的性能表现会这么好。
ENV

RPS 基准测试
// 1000 connections, 500 messages/second, 1000 Byte Payload
tcpkali -c 1000 --connect-rate 500 -r 500 -T 30s -f assets/1K.txt --ws 127.0.0.1:${port}/connect
- gws
Destination: [127.0.0.1]:8000
Interface lo address [127.0.0.1]:0
Using interface lo to connect to [127.0.0.1]:8000
Ramped up to 1000 connections.
Total data sent: 12919.8 MiB (13547411965 bytes)
Total data received: 12854.5 MiB (13478908970 bytes)
Bandwidth per channel: 7.178⇅ Mbps (897.2 kBps)
Aggregate bandwidth: 3594.175↓, 3612.441↑ Mbps
Packet rate estimate: 316194.9↓, 581166.7↑ (3↓, 2↑ TCP MSS/op)
Test duration: 30.0017 s.
- gorilla
Destination: [127.0.0.1]:8001
Interface lo address [127.0.0.1]:0
Using interface lo to connect to [127.0.0.1]:8001
Ramped up to 1000 connections.
Total data sent: 7077.0 MiB (7420776528 bytes)
Total data received: 7089.8 MiB (7434174595 bytes)
Bandwidth per channel: 3.961⇅ Mbps (495.1 kBps)
Aggregate bandwidth: 1982.319↓, 1978.746↑ Mbps
Packet rate estimate: 272613.9↓, 173441.2↑ (2↓, 12↑ TCP MSS/op)
Test duration: 30.0019 s.
- nhooyr
Destination: [127.0.0.1]:8002
Interface lo address [127.0.0.1]:0
Using interface lo to connect to [127.0.0.1]:8002
Ramped up to 1000 connections.
Total data sent: 5103.5 MiB (5351431830 bytes)
Total data received: 5140.6 MiB (5390317539 bytes)
Bandwidth per channel: 2.856⇅ Mbps (357.0 kBps)
Aggregate bandwidth: 1437.359↓, 1426.990↑ Mbps
Packet rate estimate: 135048.1↓, 124004.1↑ (1↓, 14↑ TCP MSS/op)
Test duration: 30.0012 s.
- gobwas
Destination: [127.0.0.1]:8003
Interface lo address [127.0.0.1]:0
Using interface lo to connect to [127.0.0.1]:8003
Ramped up to 1000 connections.
Total data sent: 3364.6 MiB (3528061499 bytes)
Total data received: 3440.3 MiB (3607388324 bytes)
Bandwidth per channel: 1.893⇅ Mbps (236.7 kBps)
Aggregate bandwidth: 961.961↓, 940.808↑ Mbps
Packet rate estimate: 89305.6↓, 84530.8↑ (1↓, 18↑ TCP MSS/op)
Test duration: 30.0003 s.
更多关于Golang Websocket包测试指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang Websocket包测试指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
从你提供的基准测试结果来看,gws 的性能表现确实非常出色,在相同测试条件下显著优于其他主流 WebSocket 库。这主要得益于其高效的内存管理和并发处理设计。以下是一些关键的技术分析和测试建议:
性能优势分析
gws 的高性能主要来自这几个设计:
- 零拷贝技术:减少内存分配和复制开销
- 事件驱动架构:基于 epoll/kqueue 的高效 I/O 多路复用
- 内存池优化:重用缓冲区减少 GC 压力
完整的基准测试示例
这里提供一个更全面的性能测试示例,包含连接处理和消息吞吐:
package main
import (
"log"
"net/http"
"time"
"github.com/lxzan/gws"
)
// 简单的 Echo 服务器
func main() {
upgrader := gws.NewUpgrader(&Handler{}, &gws.ServerOption{
ReadAsyncEnabled: true, // 启用异步读取
CompressEnabled: true, // 启用压缩
})
http.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) {
socket, err := upgrader.Upgrade(w, r)
if err != nil {
return
}
socket.ReadLoop() // 开始读取循环
})
log.Fatal(http.ListenAndServe(":8000", nil))
}
type Handler struct{}
func (c *Handler) OnOpen(socket *gws.Conn) {
log.Printf("连接建立: %s", socket.RemoteAddr())
}
func (c *Handler) OnClose(socket *gws.Conn, err error) {
log.Printf("连接关闭: %v", err)
}
func (c *Handler) OnPing(socket *gws.Conn, payload []byte) {
socket.WritePong(payload)
}
func (c *Handler) OnPong(socket *gws.Conn, payload []byte) {}
func (c *Handler) OnMessage(socket *gws.Conn, message *gws.Message) {
defer message.Close()
// Echo 消息回客户端
socket.WriteMessage(message.Opcode, message.Bytes())
}
压力测试脚本
创建一个自动化测试脚本,模拟真实场景:
package test
import (
"testing"
"time"
"github.com/gorilla/websocket"
"github.com/lxzan/gws"
)
// 连接压力测试
func BenchmarkGWSConnections(b *testing.B) {
// 启动服务器
go startGWSServer()
time.Sleep(100 * time.Millisecond)
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 建立连接
conn, _, err := websocket.DefaultDialer.Dial("ws://localhost:8000/connect", nil)
if err != nil {
b.Fatal(err)
}
// 发送测试消息
msg := make([]byte, 1024)
conn.WriteMessage(websocket.BinaryMessage, msg)
// 接收响应
_, _, err = conn.ReadMessage()
if err != nil {
b.Fatal(err)
}
conn.Close()
}
}
// 消息吞吐测试
func BenchmarkGWSThroughput(b *testing.B) {
conn, _, _ := websocket.DefaultDialer.Dial("ws://localhost:8000/connect", nil)
defer conn.Close()
msg := make([]byte, 1024)
b.ResetTimer()
for i := 0; i < b.N; i++ {
conn.WriteMessage(websocket.BinaryMessage, msg)
_, _, err := conn.ReadMessage()
if err != nil {
b.Fatal(err)
}
}
}
func startGWSServer() {
upgrader := gws.NewUpgrader(&gwsHandler{}, &gws.ServerOption{})
http.HandleFunc("/connect", func(w http.ResponseWriter, r *http.Request) {
socket, _ := upgrader.Upgrade(w, r)
socket.ReadLoop()
})
http.ListenAndServe(":8000", nil)
}
type gwsHandler struct{}
func (h *gwsHandler) OnOpen(c *gws.Conn) {}
func (h *gwsHandler) OnClose(c *gws.Conn, err error) {}
func (h *gwsHandler) OnPing(c *gws.Conn, payload []byte) { c.WritePong(payload) }
func (h *gwsHandler) OnPong(c *gws.Conn, payload []byte) {}
func (h *gwsHandler) OnMessage(c *gws.Conn, message *gws.Message) {
c.WriteMessage(message.Opcode, message.Bytes())
message.Close()
}
内存使用监控
添加内存分析来验证 GC 效率:
func TestGWSMemoryUsage(t *testing.T) {
var m1, m2 runtime.MemStats
runtime.ReadMemStats(&m1)
// 创建大量连接
var conns []*gws.Conn
for i := 0; i < 10000; i++ {
// 模拟连接创建
}
runtime.GC()
runtime.ReadMemStats(&m2)
allocated := m2.TotalAlloc - m1.TotalAlloc
t.Logf("内存分配: %.2f MB", float64(allocated)/1024/1024)
}
你的测试结果已经充分展示了 gws 的性能优势。通过上述更全面的测试方案,可以进一步验证库在不同场景下的稳定性。特别是在高并发连接和消息吞吐方面,gws 的设计确实带来了显著的性能提升。

