V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
Nazz
V2EX  ›  程序员

gws: 性能与用户友好并存的 go websocket server

  •  
  •   Nazz · 2023-01-12 20:38:40 +08:00 · 1828 次点击
    这是一个创建于 716 天前的主题,其中的信息可能已经有所发展或是发生改变。

    全程用爱发电、花了很多时间肝代码,所以厚着脸皮,来求一波 star, issue

    话不多说先上测试结果

    • machine: Ubuntu 20.04LTS VM (4C8T)
    • client: tcpkali
    Server Connection Send Speed(msg/s) Payload size Download / Upload Bandwidth(Mbps)
    gws 200 20000 2.34KiB 11614.442↓ 11556.101↑
    gorilla 200 20000 2.34KiB 4244.398↓ 4188.711↑
    gws 2000 500 2.34KiB 7906.156↓ 7914.797↑
    gorilla 2000 500 2.34KiB 4263.545↓ 4260.077↑
    gws 5000 50 2.34KiB 4941.188↓ 4943.667↑
    gorilla 5000 50 2.34KiB -
    gws 10000 10 2.34KiB 1980.124↓ 1977.561↑
    gorilla 10000 10 2.34KiB 1972.556↓ 1979.981↑
    gws 10000 20 2.34KiB 3952.788↓ 3959.341↑
    gorilla 10000 20 2.34KiB -

    - means exception

    亮点

    • 无依赖
    • 不需要开启额外协程监听消息, 处理各种事件
    • 读写消息不返回错误, 它们在 gws 内部被适当的处理了
    • 重新实现了 bytes.Buffer, 大部分情况不会动态扩容
    • 通过了 autobahn-testsuite 所有的 WebSocket Protocol 测试用例

    安装

    go get -v github.com/lxzan/gws@latest
    

    核心接口

    type Event interface {
        OnOpen(socket *Conn)
        OnError(socket *Conn, err error)
        OnClose(socket *Conn, code uint16, reason []byte)
        OnPing(socket *Conn, payload []byte)
        OnPong(socket *Conn, payload []byte)
        OnMessage(socket *Conn, message *Message)
    }
    

    快速开始

    package main
    
    import (
    	"fmt"
    	"github.com/lxzan/gws"
    	"net/http"
    )
    
    func main() {
    	var config = &gws.Config{
    		CompressEnabled:   true,
    		CheckTextEncoding: true,
    		MaxContentLength:  32 * 1024 * 1024,
    		ResponseHeader:    http.Header{"Server": []string{"gws"}},
    	}
    	var handler = new(WebSocket)
    	http.HandleFunc("/connect", func(writer http.ResponseWriter, request *http.Request) {
    		socket, err := gws.Accept(writer, request, handler, config)
    		if err != nil {
    			return
    		}
    		socket.Listen()
    	})
    
    	_ = http.ListenAndServe(":3000", nil)
    }
    
    type WebSocket struct{}
    
    func (c *WebSocket) OnClose(socket *gws.Conn, code uint16, reason []byte) {
    	fmt.Printf("onclose: code=%d, payload=%s\n", code, string(reason))
    }
    
    func (c *WebSocket) OnError(socket *gws.Conn, err error) {
    	fmt.Printf("onerror: err=%s\n", err.Error())
    }
    
    func (c *WebSocket) OnOpen(socket *gws.Conn) {
    	println("connected")
    }
    
    func (c *WebSocket) OnPing(socket *gws.Conn, payload []byte) {
    	fmt.Printf("onping: payload=%s\n", string(payload))
    	socket.WritePong(payload)
    }
    
    func (c *WebSocket) OnPong(socket *gws.Conn, payload []byte) {}
    
    func (c *WebSocket) OnMessage(socket *gws.Conn, message *gws.Message) {
    	socket.WriteMessage(message.Typ(), message.Bytes())
    	message.Close()
    }
    

    测试

    docker run -it --rm \
        -v ${PWD}/config:/config \
        -v ${PWD}/reports:/reports \
        crossbario/autobahn-testsuite \
        wstest -m fuzzingclient -s /config/fuzzingclient.json
    
    tiedan
        1
    tiedan  
       2023-01-12 20:48:31 +08:00
    有个个人小项目,打算用一下试试
    Nazz
        2
    Nazz  
    OP
       2023-01-12 20:52:52 +08:00
    @tiedan 欢迎欢迎
    lizhenda
        3
    lizhenda  
       2023-01-13 09:21:09 +08:00
    已 star ,正好在用 gorilla ,初步看 gws 还是蛮简洁的。
    Nazz
        4
    Nazz  
    OP
       2023-01-13 11:37:12 +08:00 via Android
    @lizhenda 感谢支持
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1799 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:24 · PVG 00:24 · LAX 08:24 · JFK 11:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.