gev 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库,底层并不使用 golang net 库,而是使用 epoll 和 kqueue,所以它并不支持 Windows。html
Golang 的 goroutine 虽然很是轻量,可是每启动一个 goroutine 仍须要 4k 左右的内存。读了鸟窝大佬的文章【百万 Go TCP 链接的思考: epoll方式减小资源占用】后,便去研究了了下 evio。linux
evio 虽然很是快,可是仍然存在一些问题,便尝试去优化它,因而有了 eviop 项目。关于 evio 的问题能够看个人另外一篇博文 【Golang 网络库evio一些问题/bug和思考】。在优化 evio 完成 eviop 的过程当中,由于其网络模型的缘故,越发感受修改它很是麻烦,成本比从新搞一个还高。git
最终决定本身重搞一个,更加轻量,不须要的全去掉。加上大学时学习过 muduo ,便参考 muduo 的使用的 Reactor 模型实现 gev 。github
在 linux 环境下,gev 底层使用 epoll ,这是 gev 会专一优化的地方。在 mac 下底层使用 kqueue,可能不会过多关注这部分的优化,毕竟不多有用 mac 作服务器的(Windows 环境"暂"不支持)。golang
gev
只使用极少的 goroutine, 一个 goroutine 负责监听客户端链接,其余 goroutine (work 协程)负责处理已链接客户端的读写事件,work 协程数量能够配置,默认与运行主机 CPU 数量相同。bash
测试环境 Ubuntu18.04服务器
和同类库的简单性能比较, 压测方式与 evio 项目相同。网络
限制 GOMAXPROCS=1,1 个 work 协程多线程
限制 GOMAXPROCS=1,4 个 work 协程app
限制 GOMAXPROCS=4,4 个 work 协程
go get -u github.com/Allenxuxu/gev
复制代码
package main
import (
"flag"
"strconv"
"log"
"github.com/Allenxuxu/gev"
"github.com/Allenxuxu/gev/connection"
"github.com/Allenxuxu/ringbuffer"
)
type example struct{}
func (s *example) OnConnect(c *connection.Connection) {
log.Println(" OnConnect : ", c.PeerAddr())
}
func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) {
//log.Println("OnMessage")
first, end := buffer.PeekAll()
out = first
if len(end) > 0 {
out = append(out, end...)
}
buffer.RetrieveAll()
return
}
func (s *example) OnClose() {
log.Println("OnClose")
}
func main() {
handler := new(example)
var port int
var loops int
flag.IntVar(&port, "port", 1833, "server port")
flag.IntVar(&loops, "loops", -1, "num loops")
flag.Parse()
s, err := gev.NewServer(handler,
gev.Network("tcp"),
gev.Address(":"+strconv.Itoa(port)),
gev.NumLoops(loops))
if err != nil {
panic(err)
}
s.Start()
}
复制代码
本项目受 evio 启发,参考 muduo 实现。