# gev
[![Github Actions](https://github.com/Allenxuxu/gev/workflows/CI/badge.svg)](https://github.com/Allenxuxu/gev/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/Allenxuxu/gev)](https://goreportcard.com/report/github.com/Allenxuxu/gev)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a2a55fe9c0c443e198f588a6c8026cd0)](https://www.codacy.com/manual/Allenxuxu/gev?utm_source=github.com&utm_medium=referral&utm_content=Allenxuxu/gev&utm_campaign=Badge_Grade)
[![GoDoc](https://godoc.org/github.com/Allenxuxu/gev?status.svg)](https://godoc.org/github.com/Allenxuxu/gev)
[![LICENSE](https://img.shields.io/badge/LICENSE-MIT-blue)](https://github.com/Allenxuxu/gev/blob/master/LICENSE)
[![Code Size](https://img.shields.io/github/languages/code-size/Allenxuxu/gev.svg?style=flat)](https://img.shields.io/github/languages/code-size/Allenxuxu/gev.svg?style=flat)
### [[English]](README-EN.md)
`gev` 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库,支持自定义协议,轻松快速搭建高性能服务器。
## 特点
- 基于 epoll 和 kqueue 实现的高性能事件循环
- 支持多核多线程
- 动态扩容 Ring Buffer 实现的读写缓冲区
- 异步读写
- SO_REUSEPORT 端口重用支持
- 支持 WebSocket
- 支持定时任务,延时任务
- 支持自定义协议
## 网络模型
`gev` 只使用极少的 goroutine, 一个 goroutine 负责监听客户端连接,其他 goroutine (work 协程)负责处理已连接客户端的读写事件,work 协程数量可以配置,默认与运行主机 CPU 数量相同。
![image](benchmarks/out/reactor.png)
## 性能测试
> 测试环境 Ubuntu18.04 | 4 Virtual CPUs | 4.0 GiB
### 吞吐量测试
限制 GOMAXPROCS=1(单线程),1 个 work 协程
![image](benchmarks/out/gev11.png)
限制 GOMAXPROCS=4,4 个 work 协程
![image](benchmarks/out/gev44.png)
### 其他测试
<details>
<summary> 速度测试 </summary>
和同类库的简单性能比较, 压测方式与 evio 项目相同。
- gnet
- eviop
- evio
- net (标准库)
限制 GOMAXPROCS=1,1 个 work 协程
![image](benchmarks/out/echo-1c-1loops.png)
限制 GOMAXPROCS=1,4 个 work 协程
![image](benchmarks/out/echo-1c-4loops.png)
限制 GOMAXPROCS=4,4 个 work 协程
![image](benchmarks/out/echo-4c-4loops.png)
</details>
## 安装
```bash
go get -u github.com/Allenxuxu/gev
```
## 快速入门
### echo demo
```go
package main
import (
"flag"
"strconv"
"github.com/Allenxuxu/gev"
"github.com/Allenxuxu/gev/connection"
)
type example struct{}
func (s *example) OnConnect(c *connection.Connection) {
//log.Println(" OnConnect : ", c.PeerAddr())
}
func (s *example) OnMessage(c *connection.Connection, ctx interface{}, data []byte) (out []byte) {
//log.Println("OnMessage")
out = data
return
}
func (s *example) OnClose(c *connection.Connection) {
//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.Address(":"+strconv.Itoa(port)),
gev.NumLoops(loops))
if err != nil {
panic(err)
}
s.Start()
}
```
Handler 是一个接口,我们的程序必须实现它。
```go
type Handler interface {
OnConnect(c *connection.Connection)
OnMessage(c *connection.Connection, ctx interface{}, data []byte) []byte
OnClose(c *connection.Connection)
}
func NewServer(handler Handler, opts ...Option) (server *Server, err error)
```
OnMessage 会在一个完整的数据帧到来时被回调。用户可此可以拿到数据,处理业务逻辑,并返回需要发送的数据。
在有数据到来时,gev 并非立刻回调 OnMessage ,而是会先回调一个 UnPacket 函数。大概执行逻辑如下:
```go
ctx, receivedData := c.protocol.UnPacket(c, buffer)
if ctx != nil || len(receivedData) != 0 {
sendData := c.OnMessage(c, ctx, receivedData)
if len(sendData) > 0 {
return c.protocol.Packet(c, sendData)
}
}
```
![protocol](benchmarks/out/protocol.png)
UnPacket 函数中会查看 ringbuffer 中的数据是否是一个完整的数据帧,如果是则会将数据拆包并返回 payload 数据;如果还不是一个完整的数据帧,则直接返回。
UnPacket 的返回值 `(interface{}, []byte)` 会作为 OnMessage 的入参 `ctx interface{}, data []byte` 被传入并回调。`ctx` 被设计用来传递在 UnPacket 函数中解析数据帧时生成的特殊信息(复杂的数据帧协议会需要),`data` 则是用来传递 payload 数据。
```go
type Protocol interface {
UnPacket(c *Connection, buffer *ringbuffer.RingBuffer) (interface{}, []byte)
Packet(c *Connection, data []byte) []byte
}
type DefaultProtocol struct{}
func (d *DefaultProtocol) UnPacket(c *Connection, buffer *ringbuffer.RingBuffer) (interface{}, []byte) {
ret := buffer.Bytes()
buffer.RetrieveAll()
return nil, ret
}
func (d *DefaultProtocol) Packet(c *Connection, data []byte) []byte {
return data
}
```
如上,`gev` 提供一个默认的 Protocol 实现,会将接受缓冲区中( ringbuffer )的所有数据取出。
在实际使用中,通常会有自己的数据帧协议,`gev` 可以以插件的形式来设置:在创建 Server 的时候通过可变参数设置。
```go
s, err := gev.NewServer(handler,gev.Protocol(&ExampleProtocol{}))
```
更详细的使用方式可以参考示例:[自定义协议](example/protocol)
Connection 还提供 Send 方法来发送数据。Send 并不会立刻发送数据,而是先添加到 event loop 的任务队列中,然后唤醒 event loop 去发送。
更详细的使用方式可以参考示例:[服务端定时推送](example/pushmessage/main.go)
```go
func (c *Connection) Send(buffer []byte) error
```
Connection ShutdownWrite 会关闭写端,从而断开连接。
更详细的使用方式可以参考示例:[限制最大连接数](example/maxconnection/main.go)
```go
func (c *Connection) ShutdownWrite() error
```
[RingBuffer](https://github.com/Allenxuxu/ringbuffer) 是一个动态扩容的循环缓冲区实现。
### WebSocket 支持
WebSocket 协议构建在 TCP 协议之上的,所以 `gev` 无需内置它,而是通过插件的形式提供支持,在 `plugins/websocket` 目录。
```go
type Protocol struct {
upgrade *ws.Upgrader
}
func New(u *ws.Upgrader) *Protocol {
return &Protocol{upgrade: u}
}
func (p *Protocol) UnPacket(c *connection.Connection, buffer *ringbuffer.RingBuffer) (ctx interface{}, out []byte) {
upgraded := c.Context()
if upgraded == nil {
var err error
out, _, err = p.upgrade.Upgrade(buffer)
if err != nil {
log.Println("Websocket Upgrade :", err)
return
}
c.SetContext(true)
} else {
header, err := ws.VirtualReadHeader(buffer)
if err != nil {
log.Println(err)
return
}
if buffer.VirtualLength() >= int(header.Length) {
buffer.VirtualFlush()
payload := make([]byte, int(header.Length))
_, _ = buffer.Read(payload)
if header.Masked {
ws.Cipher(payload, header.Mask, 0)
}
ctx = &header
out = payload
} else {
buffer.VirtualRevert()
}
}
return
}
func (p *Protocol) Packet(c *connection.Connection, data []byte) []byte {
return data
}
```
详细实现可以插件实现查看 [源码](plugins/websocket),使用方式可以查看 websocket [示例](example/websocket)
## 示例
<details>
<summary> echo server</summary>
```go
package main
import (
"flag"
"strconv"
"github.com/Allenxuxu/gev"
"github.com/Allenxuxu/gev/connection"
)
type example struct{}
func (s *example) OnConnect(c *connection.Connection) {
//log.Println(" OnConnect : ", c.PeerAddr())
}
func (s *example) OnMessage(c *connection.Connection, ctx interface{}, data []byte) (out []byte) {
//log.Println("OnMessage")
out = data
return
}
func (s *example) OnClose(c *connection.Connection) {
//log.Println("OnClose")
}
func main() {
handle
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
arp -包arp实现ARP协议,如RFC 826中所述。 buffstreams - 通过TCP流化协议缓冲区数据变得容易。 canopus - CoAP客户端/服务器实施(RFC 7252)。 cidranger - Go的快速IP到CIDR查找。 dhcp6 - 软件包dhcp6实现了DHCPv6服务器,如RFC 3315中所述。 dns - 使用DNS的Go库。 ether - 用于发送和接收以太网帧的跨平台Go软件包。 ethernet - 程序包ethernet实施IEEE 802.3以太网II帧和IEEE 802.1Q VLAN标签的封送处理。 fasthttp - 软件包fasthttp是Go的一种快速HTTP实现,比net / http快10倍。 fortio - 负载测试库和命令行工具,高级回显服务器和Web UI。允许指定设置的每秒查询负载,并记录延迟直方图和其他有用的统计数据并对其进行图形化。Tcp,Http,gRPC。 ftp 程序包ftp实现RFC 959中所述的FTP客户端。 gev - gev是基于Reactor模式的轻量级,快速,无阻塞的TCP网络库。
资源推荐
资源详情
资源评论
收起资源包目录
gev 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库.rar (65个子文件)
gev 是一个轻量、快速的基于 Reactor 模式的非阻塞 TCP 网络库
新建文本文档.txt 19B
gev-master
eventloop
eventloop_test.go 382B
eventloop.go 2KB
options.go 1KB
server_test.go 2KB
go.mod 602B
plugins
websocket
wrap.go 2KB
ws
read.go 2KB
nonce.go 2KB
http.go 9KB
ws.go 10KB
util.go 2KB
LICENSE 1KB
errors.go 5KB
frame.go 8KB
write.go 1KB
cipher.go 2KB
util
util.go 2KB
README.md 102B
protocol.go 1KB
.github
workflows
go.yml 924B
go.sum 8KB
LICENSE 1KB
README-EN.md 13KB
everyscheduler.go 173B
poller
poller.go 328B
epoll.go 4KB
poller_test.go 456B
kqueue.go 3KB
benchmarks
gnet-echo-server
main.go 1KB
net-echo-server
main.go 971B
client
main.go 2KB
out
echo.png 17KB
gev11.png 30KB
echo-1c-1loops.txt 3KB
echo-4c-4loops.txt 3KB
echo-1c-1loops.png 17KB
reactor.png 31KB
echo-4c-4loops.png 18KB
gev44.png 37KB
echo.txt 3KB
echo-1c-4loops.txt 3KB
protocol.png 22KB
echo-1c-4loops.png 17KB
bench-echo.sh 1KB
bench-pingpong.sh 1KB
eviop-echo-server
main.go 1KB
evio-echo-server
main.go 1KB
.gitignore 11B
connection
protocol.go 654B
connection.go 5KB
server.go 3KB
.gitignore 199B
listener
listener.go 2KB
example
protocol
client
main.go 1KB
server.go 895B
protocol.go 972B
echo
echo.go 820B
pushmessage
main.go 2KB
websocket
wsserver_test.go 2KB
wsserver.go 442B
main.go 1KB
maxconnection
main.go 1KB
README.md 13KB
log
log.go 3KB
共 65 条
- 1
资源评论
野生的狒狒
- 粉丝: 3390
- 资源: 2436
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- (源码)基于SpringBoot和MyBatis的教育管理系统.zip
- audio1244261864.m4a
- yolo-world.zip
- (源码)基于SpringBoot框架的远程控制门禁系统.zip
- 精选微信小程序源码:早教幼儿启蒙小程序(含源码+源码导入视频教程&文档教程,亲测可用)
- (源码)基于SpringBoot和Vue的论坛系统.zip
- 运维系列亲测有效:mobaxterm怎么删除已保存的密码
- (源码)基于Bash的Linux环境管理利器-快速启动系统配置文件管理器.zip
- Kylin操作系统在虚拟环境下的安装与配置指南
- (源码)基于STM32F0系列微控制器的时钟配置系统.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功