gnet —— 高性能和轻量级的网络库
gnet
是一个基于事件驱动的高性能和轻量级网络框架。它直接使用 epoll 和 kqueue 系统调用而非标准 Golang 网络包:net 来构建网络应用,它的工作原理类似两个开源的网络库:netty 和 libuv。
这个项目存在的价值是提供一个在网络包处理方面能和 Redis、Haproxy 这两个项目具有相近性能的 Go 语言网络服务器框架。
gnet
的亮点在于它是一个高性能、轻量级、非阻塞的纯 Go 实现的传输层(TCP/UDP/Unix-Socket)网络框架,开发者可以使用 gnet
来实现自己的应用层网络协议(HTTP、RPC、Redis、WebSocket 等等),从而构建出自己的应用层网络应用:比如在 gnet
上实现 HTTP 协议就可以创建出一个 HTTP 服务器 或者 Web 开发框架,实现 Redis 协议就可以创建出自己的 Redis 服务器等等。
gnet
衍生自另一个项目:evio
,但性能远胜之。
功能
- 高性能 的基于多线程/Go程网络模型的 event-loop 事件驱动
- 内置 Round-Robin 轮询负载均衡算法
- 内置 goroutine 池,由开源库 ants 提供支持
- 内置 bytes 内存池,由开源库 pool 提供支持
- 简洁的 APIs
- 基于 Ring-Buffer 的高效内存利用
- 支持多种网络协议:TCP、UDP、Unix Sockets
- 支持两种事件驱动机制:Linux 里的 epoll 以及 FreeBSD 里的 kqueue
- 支持异步写操作
- 灵活的事件定时器
- SO_REUSEPORT 端口重用
- 内置多种编解码器,支持对 TCP 数据流分包:LineBasedFrameCodec, DelimiterBasedFrameCodec, FixedLengthFrameCodec 和 LengthFieldBasedFrameCodec,参考自 netty codec,而且支持自定制编解码器
- 支持 Windows 平台,基于 IOCP 事件驱动机制 Go 标准网络库
- 加入更多的负载均衡算法:随机、最少连接、一致性哈希等等
- 支持 TLS
- 实现
gnet
客户端
核心设计
多线程/Go程网络模型
主从多 Reactors
gnet
重新设计开发了一个新内置的多线程/Go程网络模型:『主从多 Reactors』,这也是 netty
默认的多线程网络模型,下面是这个模型的原理图:
它的运行流程如下面的时序图:
主从多 Reactors + 线程/Go程池
你可能会问一个问题:如果我的业务逻辑是阻塞的,那么在 EventHandler.React
注册方法里的逻辑也会阻塞,从而导致阻塞 event-loop 线程,这时候怎么办?
正如你所知,基于 gnet
编写你的网络服务器有一条最重要的原则:永远不能让你业务逻辑(一般写在 EventHandler.React
里)阻塞 event-loop 线程,否则的话将会极大地降低服务器的吞吐量,这也是 netty
的一条最重要的原则。
我的回答是,基于gnet
的另一种多线程/Go程网络模型:『带线程/Go程池的主从多 Reactors』可以解决阻塞问题,这个新网络模型通过引入一个 worker pool 来解决业务逻辑阻塞的问题:它会在启动的时候初始化一个 worker pool,然后在把 EventHandler.React
里面的阻塞代码放到 worker pool 里执行,从而避免阻塞 event-loop 线程,
模型的架构图如下所示:
它的运行流程如下面的时序图:
gnet
通过利用 ants goroutine 池(一个基于 Go 开发的高性能的 goroutine 池 ,实现了对大规模 goroutines 的调度管理、goroutines 复用)来实现『主从多 Reactors + 线程/Go程池』网络模型。关于 ants
的全部功能和使用,可以在 ants 文档 里找到。
gnet
内部集成了 ants
以及提供了 pool.NewWorkerPool
方法来初始化一个 ants
goroutine 池,然后你可以把 EventHandler.React
中阻塞的业务逻辑提交到 goroutine 池里执行,最后在 goroutine 池里的代码调用 gnet.Conn.AsyncWrite
方法把处理完阻塞逻辑之后得到的输出数据异步写回客户端,这样就可以避免阻塞 event-loop 线程。
有关在 gnet
里使用 ants
goroutine 池的细节可以到这里进一步了解。
自动扩容的 Ring-Buffer
gnet
内置了inbound 和 outbound 两个 buffers,基于 Ring-Buffer 原理实现,分别用来缓冲输入输出的网络数据以及管理内存。
对于 TCP 协议的流数据,使用 gnet
不需要业务方为了解析应用层协议而自己维护和管理 buffers,gnet
会替业务方完成缓冲和管理网络数据的任务,降低业务代码的复杂性以及降低开发者的心智负担,使得开发者能够专注于业务逻辑而非一些底层功能。
性能测试
同类型的网络库性能对比
Linux (epoll)
系统参数
# Machine information OS : Ubuntu 18.04/x86_64 CPU : 8 Virtual CPUs Memory : 16.0 GiB # Go version and configurations Go Version : go1.12.9 linux/amd64 GOMAXPROCS=8
Echo Server
HTTP Server
FreeBSD (kqueue)
系统参数
# Machine information OS : macOS Mojave 10.14.6/x86_64 CPU : 4 CPUs Memory : 8.0 GiB # Go version and configurations Go Version : go version go1.12.9 darwin/amd64 GOMAXPROCS=4
Echo Server
HTTP Server
相关文章
- A Million WebSockets and Go
- Going Infinite, handling 1M websockets connections in Go
- Go netpoll I/O 多路复用构建原生网络模型之源码深度解析
- gnet: 一个轻量级且高性能的 Golang 网络库

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
每日一博 | 遗传算法如何模拟大自然的进化?
达尔文:物竞天择,适者生存。 遗传算法概述 遗传算法(Genetic Algorithm,GA)的算法思想来源于达尔文的进化论学说和Mendel的遗传理论,本质是模拟种群个体不断进化以逐渐适应环境的过程。遗传算法通过自然选择、交叉、变异等遗传操作模拟种群进化过程,使种群中个体的优良基因得以保留,提高个体的适应能力,进而不断增强对环境的适应能力。见下表: 从上表中,我们可以看到遗传算法是以染色体形式对问题的解进行描述,通过对编码串类似自然进化的遗传操作,来完成新个体的产生。当新个体产生后,我们就可以根据个体的适应值,遵循自然选择法则,适者生存来选取优秀个体再次进化,直到进化完成。 其中,遗传算法的流程图如下: 在算法初始化时,首先随机产生一批初始种群,根据适应度函数公式计算种群中各个染色体的适应度值;进一步,按照适者生存、优胜劣汰的法则,选择种群中的个体进行复制、交叉、变异的遗传操作产生出子代染色体,个体适应度越大被选择进行遗传操作的概率越高,从而将种群中的优良基因进行保留同时适应度较差的个体将逐渐被淘汰;最后,进化多代后达到算法终止条件,算法收敛到某个对环境适应性最好的染色体上,这个染...
- 下一篇
GitHub Advisory Database 现已支持 npm audit
供应链安全是当今软件开发中最重要的部分之一,GitHub 为了让开发者能够轻松实现安全开发,此前推出了一个名为 Advisory Database 的开放安全咨询数据库,它专注于为开发者提供高质量、可操作的漏洞信息。 继上个月 Advisory Database 扩展了对 Rust 编程语言的支持后(点击查看报道),Advisory Database 的覆盖范围扩大到八个支持的编程语言生态:Composer (PHP)、Go、Maven、npm、NuGet、pip、RubyGems 和 Rust。近日 GitHub 为了进一步增强 npm 的安全性,为 Advisory Database 引入了 npm audit 的支持。 npm audit 是一个命令,你可以在 Node.js 应用程序中运行,以扫描你的项目依赖中已知的安全漏洞 —— 扫描完成后你会得到一个 URL,通过它你可以了解漏洞的更多详情,以及关于哪些版本已经修复了这个漏洞的信息。此外,npm install 命令也会使用这些信息来给你一个简单的问题概述。 而 Advisory Database 包含已映射到 GitHub...
相关文章
文章评论
共有0条评论来说两句吧...