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

image.png

特性方面, 主要有:

  1. 无依赖
  2. 支持连接多路复用, 在一个连接上并行处理多条消息, 控制好了并发上限
  3. 支持异步非阻塞写入, 且不增加常驻协程

每个连接上都有两个任务队列, 一个读一个写, 它们非常轻量, 并行度分别是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
}

codebeast
51 声望0 粉丝