[gev] 一個輕量、快速的基於 Reactor 模式的非阻塞 TCP 網路庫

惜朝發表於2019-09-26

gev

`gev` 是一個輕量、快速的基於 Reactor 模式的非阻塞 TCP 網路庫。

特點

- 基於 epoll 和 kqueue 實現的高效能事件迴圈 - 支援多核多執行緒 - 動態擴容 Ring Buffer 實現的讀寫緩衝區 - 非同步讀寫 - SO_REUSEPORT 埠重用支援

網路模型

`gev` 只使用極少的 goroutine, 一個 goroutine 負責監聽客戶端連線,其他 goroutine (work 協程)負責處理已連線客戶端的讀寫事件,work 協程數量可以配置,預設與執行主機 CPU 數量相同。
https://i.iter01.com/images/1649e2f5b0f1e03bf54f04a895ebb07fb21861f7e0002728179a44a9b698ab40.png

效能測試

> 測試環境 Ubuntu18.04 | 4 Virtual CPUs | 4.0 GiB

吞吐量測試

限制 GOMAXPROCS=1(單執行緒),1 個 work 協程
https://i.iter01.com/images/c640d2ef4d8955036f82ea268b62e980018f89e15eb41ebe64fbb34004d15576.png
限制 GOMAXPROCS=4,4 個 work 協程
https://i.iter01.com/images/fc8b9858872066f55a47630b0c693b1e0915a395ccd6b398c2f0583930d880d3.png

其他測試

速度測試

和同類庫的簡單效能比較, 壓測方式與 evio 專案相同。 - gnet - eviop - evio - net (標準庫) 限制 GOMAXPROCS=1,1 個 work 協程
https://i.iter01.com/images/61f6c3e1dbf0bb2c08169aae41551b93f9cc20b74f1da4663a732a3e70b01158.png
限制 GOMAXPROCS=1,4 個 work 協程
https://i.iter01.com/images/279792a2349bbc15351300fc79d07866c40009421b21d7b44434f9b7f0849cee.png
限制 GOMAXPROCS=4,4 個 work 協程
https://i.iter01.com/images/61f6c3e1dbf0bb2c08169aae41551b93f9cc20b74f1da4663a732a3e70b01158.png

安裝 gev

```bash go get -u github.com/Allenxuxu/gev ```

快速入門

```go package main import ( "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(c *connection.Connection) { log.Println("OnClose") } func main() { handler := new(example) s, err := gev.NewServer(handler, gev.Address(":1833"), gev.NumLoops(2), gev.ReusePort(true)) if err != nil { panic(err) } s.Start() } ``` Handler 是一個介面,我們的程式必須實現它。 ```go type Handler interface { OnConnect(c *connection.Connection) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) []byte OnClose(c *connection.Connection) } func NewServer(handler Handler, opts ...Option) (server *Server, err error) { ``` 在訊息到來時,gev 會回撥 OnMessage ,在這個函式中可以通過返回一個切片來傳送資料給客戶端。 ```go func (s *example) OnMessage(c *connection.Connection, buffer *ringbuffer.RingBuffer) (out []byte) ``` Connection 還提供 Send 方法來傳送資料。Send 並不會立刻傳送資料,而是先新增到 event loop 的任務佇列中,然後喚醒 event loop 去傳送。 更詳細的使用方式可以參考示例:[服務端定時推送] ```go func (c *Connection) Send(buffer []byte) error ``` Connection ShutdownWrite 會關閉寫端,從而斷開連線。 更詳細的使用方式可以參考示例:[限制最大連線數] ```go func (c *Connection) ShutdownWrite() error ```

➡️➡️ https://github.com/Allenxuxu/gev



相關文章