gws 是一款由 golang
开发的高性能 websocket
库, 提供 websocket event api
:
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)
}
支持大部分 RFC
标准:
- 接收分片消息
- 发送关闭帧
- ping/pong
- deflate数据压缩
- 使用bufio读写消息
得益于高效的协议解析器, 相比其他库 gws
拥有更高的 IOPS
, 更低的延迟和 CPU
占用率. 但是因为 bufio
的使用, 内存占用会高一些.
$ tcpkali -c 1000 --connect-rate 500 -r 1000 -T 300s -f assets/1K.txt --ws 127.0.0.1:${port}/connect
特性方面, 主要有:
- 无依赖
- 支持连接多路复用, 在一个连接上并行处理多条消息, 控制好了并发上限
- 支持异步非阻塞写入, 且不增加常驻协程
每个连接上都有两个任务队列, 一个读一个写, 它们非常轻量, 并行度分别是8(默认值)和1. 读队列用来并行处理请求, 写队列用来处理异步写入, 非常适合消息广播场景. workerQueue
没有使用 channel
, 它依赖递归进行任务调度, 所有任务执行完毕协程便会退出.
type (
workerQueue struct {
mu sync.Mutex // 锁
q []asyncJob // 任务队列
maxConcurrency int32 // 最大并发
curConcurrency int32 // 当前并发
capacity int // 容量
}
asyncJob func()
)
// 获取一个任务
func (c *workerQueue) getJob(delta int32) asyncJob {
c.mu.Lock()
defer c.mu.Unlock()
c.curConcurrency += delta
if c.curConcurrency >= c.maxConcurrency {
return nil
}
if n := len(c.q); n == 0 {
return nil
}
var result = c.q[0]
c.q = c.q[1:]
c.curConcurrency++
return result
}
// 递归地执行任务
func (c *workerQueue) do(job asyncJob) {
job()
if nextJob := c.getJob(-1); nextJob != nil {
c.do(nextJob)
}
}
// Push 追加任务, 有资源空闲的话会立即执行
func (c *workerQueue) Push(job asyncJob) error {
c.mu.Lock()
if n := len(c.q); n >= c.capacity {
c.mu.Unlock()
return internal.ErrAsyncIOCapFull
} else {
c.q = append(c.q, job)
c.mu.Unlock()
}
if item := c.getJob(0); item != nil {
go c.do(item)
}
return nil
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。