首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
xuxu555
V2EX  ›  分享创造

[开源] gev: Go 实现基于 Reactor 模式的非阻塞 TCP 网络库

  •  3
     
  •   xuxu555 · 329 天前 · 3013 次点击
    这是一个创建于 329 天前的主题,其中的信息可能已经有所发展或是发生改变。

    gev 轻量、快速的 Golang 网络库

    https://github.com/Allenxuxu/gev

    gev 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库,底层并不使用 golang net 库,而是使用 epoll 和 kqueue,因此它并不支持 Windows。

    为什么有 gev

    Golang 的 goroutine 虽然非常轻量,但是每启动一个 goroutine 仍需要 4k 左右的内存。读了鸟窝大佬的文章 [百万 Go TCP 连接的思考: epoll 方式减少资源占用] 后,便去研究了了下 evio

    evio 虽然非常快,但是仍然存在一些问题,便尝试去优化它,于是有了 eviop 项目。关于 evio 的问题可以看我的另一篇博文 [Golang 网络库 evio 一些问题 /bug 和思考] 。在优化 evio 完成 eviop 的过程中,因为其网络模型的缘故,愈加感觉修改它非常麻烦,成本比重新搞一个还高。

    最终决定自己重搞一个,更加轻量,不需要的全去掉。加上大学时学习过 muduo ,便参考 muduo 的使用的 Reactor 模型实现 gev。

    在 linux 环境下,gev 底层使用 epoll,这是 gev 会专注优化的地方。在 mac 下底层使用 kqueue,可能不会过多关注这部分的优化,毕竟很少有用 mac 做服务器的( Windows 环境"暂"不支持)。

    特点

    • 基于 epoll 和 kqueue 实现的高性能事件循环
    • 支持多核多线程
    • 动态扩容 Ring Buffer 实现的读写缓冲区
    • 异步读写
    • SO_REUSEPORT 端口重用支持

    网络模型

    gev 只使用极少的 goroutine, 一个 goroutine 负责监听客户端连接,其他 goroutine ( work 协程)负责处理已连接客户端的读写事件,work 协程数量可以配置,默认与运行主机 CPU 数量相同。

    image.png

    性能测试

    测试环境 Ubuntu18.04

    和同类库的简单性能比较, 压测方式与 evio 项目相同。

    • gnet
    • eviop
    • evio
    • net (标准库)

    限制 GOMAXPROCS=1,1 个 work 协程

    image.png

    限制 GOMAXPROCS=1,4 个 work 协程

    image.png

    限制 GOMAXPROCS=4,4 个 work 协程

    image.png

    安装

    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 实现。

    相关文章

    14 条回复    2019-09-20 18:44:32 +08:00
    Leigg
        1
    Leigg   329 天前 via Android   ❤️ 1
    点赞!!
    xuxu555
        2
    xuxu555   329 天前
    @Leigg 感谢支持!!
    Thoxvi
        3
    Thoxvi   329 天前 via Android
    马一下,刚好在学 Go,过几天观摩一下源码😉
    caskeep
        4
    caskeep   329 天前 via iPhone
    有兴趣 mark 了
    deathscythe
        5
    deathscythe   329 天前
    点 star 为敬
    dabaibai
        6
    dabaibai   329 天前
    想折腾是不是直接用 C 写网络底层更好呢.然后套进 golang 去用
    iPhoneXI
        7
    iPhoneXI   329 天前 via Android
    https://taohuawu.club/go-event-loop-networking-library-gnet

    看到一个 gnet 项目,有点像
    xuxu555
        8
    xuxu555   329 天前
    @iPhoneXI 他这个就是 借鉴 的我的 [eviop]( https://github.com/Allenxuxu/eviop),gev 的性能对比里也和 gnet 对比了
    xuxu555
        9
    xuxu555   329 天前
    @dabaibai Go 也提供操作 epoll 的系统 API 啊
    xuxu555
        10
    xuxu555   329 天前
    @iPhoneXI gnet 目录结构和文件名都和 eviop 一样
    Cyron
        11
    Cyron   329 天前
    牛逼
    cancer0704
        12
    cancer0704   329 天前
    star
    keepeye
        13
    keepeye   329 天前
    666
    xuxu555
        14
    xuxu555   329 天前
    @Cyron 头像💯
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1017 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 79ms · UTC 22:37 · PVG 06:37 · LAX 15:37 · JFK 18:37
    ♥ Do have faith in what you're doing.