golang高性能非阻塞事件驱动网络框架插件库gnet的使用

Golang高性能非阻塞事件驱动网络框架插件库gnet的使用

gnet logo

简介

gnet是一个超快速、轻量级的事件驱动网络框架,它通过利用epollkqueue从头构建,在许多特定场景下可以实现比Go标准库net更高的性能和更低的内存消耗。

gnet与Go标准库net在网络编程理念上不同,它工作在传输层,支持TCP/UDP协议和Unix Domain Socket,使开发者能够在gnet之上实现自己的应用层协议(HTTP、RPC、WebSocket、Redis等)来构建多样化的网络服务。

特性

  • 基于多线程/goroutine网络模型的高性能事件驱动循环
  • 内置由ants库提供支持的goroutine池
  • 整个运行时无锁
  • 简洁易用的API
  • 高效、可重用和弹性的内存缓冲区
  • 支持多种协议/IPC机制:TCPUDPUnix Domain Socket
  • 多种负载均衡算法
  • 灵活的定时器事件
  • gnet客户端
  • 支持Linux、macOS、Windows和*BSD系统
  • 边缘触发的I/O支持
  • 多网络地址绑定
  • 支持将新连接注册到事件循环

安装

使用v2版本

go get -u github.com/panjf2000/gnet/v2

使用v1版本

go get -u github.com/panjf2000/gnet

使用示例

下面是一个简单的echo服务器示例,展示了如何使用gnet:

package main

import (
	"log"

	"github.com/panjf2000/gnet/v2"
)

type echoServer struct {
	gnet.BuiltinEventEngine
}

func (es *echoServer) OnTraffic(c gnet.Conn) gnet.Action {
	// 读取客户端发送的数据
	buf, _ := c.Next(-1)
	
	// 将数据原样写回客户端
	c.Write(buf)
	
	return gnet.None
}

func main() {
	echo := &echoServer{}
	
	// 启动gnet服务器
	log.Fatal(gnet.Run(echo, 
		"tcp://:9000", 
		gnet.WithMulticore(true),  // 使用多核
		gnet.WithReusePort(true),  // 启用端口复用
	))
}

性能

gnet在性能方面表现优异,在TechEmpower基准测试中排名靠前。以下是部分性能数据:

TechEmpower性能排名

许可证

gnet的源代码采用Apache-2.0许可证分发。

贡献者

欢迎贡献代码!请在提交PR前阅读贡献指南

贡献者

相关文章


更多关于golang高性能非阻塞事件驱动网络框架插件库gnet的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能非阻塞事件驱动网络框架插件库gnet的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


gnet - Go语言高性能非阻塞事件驱动网络框架

gnet是一个基于事件驱动的轻量级高性能网络框架,它直接使用epoll(kqueue)系统调用来实现非阻塞I/O,避免了标准库net的goroutine-per-connection模型带来的高内存消耗问题。

主要特性

  • 基于事件驱动的异步非阻塞网络模型
  • 支持多线程/多核处理
  • 内置负载均衡算法
  • 支持多种协议(TCP、UDP、Unix Domain Socket)
  • 高性能,低延迟
  • 简洁易用的API接口

安装

go get -u github.com/panjf2000/gnet

基本使用示例

简单的Echo服务器

package main

import (
	"log"

	"github.com/panjf2000/gnet"
)

type echoServer struct {
	*gnet.EventServer
}

func (es *echoServer) React(c gnet.Conn) (out []byte, action gnet.Action) {
	// 读取客户端数据
	data := c.Read()
	
	// 将数据原样返回
	out = data
	
	// 更新缓冲区
	c.ResetBuffer()
	
	return
}

func main() {
	echo := new(echoServer)
	
	// 启动服务器
	err := gnet.Serve(echo, "tcp://:9000", gnet.WithMulticore(true))
	if err != nil {
		log.Fatal(err)
	}
}

更完整的TCP服务器示例

package main

import (
	"log"
	"time"

	"github.com/panjf2000/gnet"
)

type tcpServer struct {
	*gnet.EventServer
}

func (ts *tcpServer) OnInitComplete(srv gnet.Server) (action gnet.Action) {
	log.Printf("TCP server is listening on %s (multi-cores: %t, loops: %d)\n",
		srv.Addr.String(), srv.Multicore, srv.NumEventLoop)
	return
}

func (ts *tcpServer) OnOpened(c gnet.Conn) (out []byte, action gnet.Action) {
	log.Printf("Connection opened: %s", c.RemoteAddr().String())
	return
}

func (ts *tcpServer) OnClosed(c gnet.Conn, err error) (action gnet.Action) {
	log.Printf("Connection closed: %s, error: %v", c.RemoteAddr().String(), err)
	return
}

func (ts *tcpServer) React(c gnet.Conn) (out []byte, action gnet.Action) {
	data := c.Read()
	
	// 业务逻辑处理
	response := processData(data)
	
	// 发送响应
	out = response
	
	// 更新缓冲区
	c.ResetBuffer()
	
	return
}

func processData(data []byte) []byte {
	// 这里添加你的业务逻辑
	return []byte("Processed: " + string(data))
}

func main() {
	tcp := &tcpServer{}
	
	// 启动服务器,配置多核处理
	err := gnet.Serve(tcp, "tcp://:9000",
		gnet.WithMulticore(true),
		gnet.WithReusePort(true),
		gnet.WithTCPKeepAlive(time.Minute*5),
		gnet.WithLogLevel(gnet.DebugLevel))
	if err != nil {
		log.Fatal(err)
	}
}

高级特性

定时任务

func (ts *tcpServer) Tick() (delay time.Duration, action gnet.Action) {
	log.Println("This is a tick event")
	return time.Second * 5, gnet.None
}

自定义编解码器

type myCodec struct{}

func (mc *myCodec) Encode(c gnet.Conn, buf []byte) ([]byte, error) {
	// 自定义编码逻辑
	return buf, nil
}

func (mc *myCodec) Decode(c gnet.Conn) ([]byte, error) {
	// 自定义解码逻辑
	return c.Read(), nil
}

// 使用时
err := gnet.Serve(echo, "tcp://:9000", 
	gnet.WithCodec(&myCodec{}))

性能优化建议

  1. 启用多核处理:gnet.WithMulticore(true)
  2. 调整事件循环数量:gnet.WithNumEventLoop(runtime.NumCPU())
  3. 使用连接池管理连接
  4. 避免在React函数中进行耗时操作
  5. 合理设置读写缓冲区大小

与标准库net对比优势

  1. 更高的吞吐量:gnet可以处理更多的并发连接
  2. 更低的内存消耗:避免了goroutine-per-connection模型
  3. 更低的延迟:基于事件驱动的模型响应更快
  4. 更好的多核利用率:内置负载均衡算法

适用场景

  • 高并发TCP/UDP服务器
  • 游戏服务器
  • 即时通讯服务
  • 代理服务器
  • 需要高性能网络处理的任何场景

gnet特别适合需要处理大量并发连接但对每个连接处理逻辑相对简单的场景,对于复杂业务逻辑的场景,可能需要结合其他框架或组件使用。

回到顶部