README

gnet

English | 🇨🇳中文

📖 Introduction

gnet is an event-driven networking framework that is fast and lightweight. It makes direct epoll and kqueue syscalls rather than using the standard Go net package and works in a similar manner as netty and libuv, which makes gnet achieve a much higher performance than Go net.

gnet is not designed to displace the standard Go net package, but to create a networking server framework for Go that performs on par with Redis and Haproxy for networking packets handling.

gnet sells itself as a high-performance, lightweight, non-blocking, event-driven networking framework written in pure Go which works on transport layer with TCP/UDP protocols and Unix Domain Socket , so it allows developers to implement their own protocols(HTTP, RPC, WebSocket, Redis, etc.) of application layer upon gnet for building diversified network applications, for instance, you get an HTTP Server or Web Framework if you implement HTTP protocol upon gnet while you have a Redis Server done with the implementation of Redis protocol upon gnet and so on.

gnet derives from the project: evio while having a much higher performance and more features.

🚀 Features

  • High-performance event-loop under networking model of multiple threads/goroutines
  • Built-in goroutine pool powered by the library ants
  • Built-in memory pool with bytes powered by the library bytebufferpool
  • Lock-free during the entire runtime
  • Concise and easy-to-use APIs
  • Efficient and reusable memory buffer: Ring-Buffer
  • Supporting multiple protocols/IPC mechanism: TCP, UDP and Unix Domain Socket
  • Supporting multiple load-balancing algorithms: Round-Robin, Source-Addr-Hash and Least-Connections
  • Supporting two event-driven mechanisms: epoll on Linux and kqueue on FreeBSD/DragonFly/Darwin
  • Supporting asynchronous write operation
  • Flexible ticker event
  • SO_REUSEPORT socket option
  • Built-in multiple codecs to encode/decode network frames into/from TCP stream: LineBasedFrameCodec, DelimiterBasedFrameCodec, FixedLengthFrameCodec and LengthFieldBasedFrameCodec, referencing netty codec, also supporting customized codecs
  • Supporting Windows platform with event-driven mechanism of IOCP Go stdlib: net
  • Implementation of gnet Client

📊 Performance

Benchmarks on TechEmpower

# Hardware Environment
CPU: 28 HT Cores Intel(R) Xeon(R) Gold 5120 CPU @ 2.20GHz
Mem: 32GB RAM
OS : Ubuntu 18.04.3 4.15.0-88-generic #88-Ubuntu
Net: Switched 10-gigabit ethernet
Go : go1.14.x linux/amd64

All language

This is the top 50 on the framework ranking of all programming languages consists of a total of 422 frameworks from all over the world where gnet is the runner-up.

Golang

This is the full framework ranking of Go and gnet tops all the other frameworks, which makes gnet the fastest networking framework in Go.

To see the full ranking list, visit TechEmpower Plaintext Benchmark.

Contrasts to the similar networking libraries

On Linux (epoll)

Test Environment
# 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

On FreeBSD (kqueue)

Test Environment
# 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

🏛 Website

Please visit the official website for more details about architecture, usage and other information of gnet.

⚠️ License

Source code in gnet is available under the MIT License.

👏 Contributors

Please read the Contributing Guidelines before opening a PR and thank you to all the developers who already made contributions to gnet!

⚓ Relevant Articles

🎡 User cases

Please feel free to add your projects here~~

💰 Backers

Support us with a monthly donation and help us continue our activities.

💎 Sponsors

Become a bronze sponsor with a monthly donation of $10 and get your logo on our README on Github.

☕️ Buy me a coffee

Please be sure to leave your name, Github account or other social media accounts when you donate by the following means so that I can add it to the list of donors as a token of my appreciation.

        

💴 Donors

Patrick Othmer Jimmy ChenZhen Mai Yang 王开帅

💵 Paid Support

If you need a tailored version of gnet and want the author to help develop it, or bug fix/fast resolution/consultation which takes a lot of effort, you can request paid support here.

🔑 JetBrains OS licenses

gnet had been being developed with GoLand IDE under the free JetBrains Open Source license(s) granted by JetBrains s.r.o., hence I would like to express my thanks here.

🔋 Sponsorship

This project is supported by:

Expand ▾ Collapse ▴

Documentation

Index

Constants

This section is empty.

Variables

var CRLFByte = byte('\n')

CRLFByte represents a byte of CRLF.


Functions

func Serve

func Serve(eventHandler EventHandler, protoAddr string, opts ...Option) (err error)

Serve starts handling events for the specified address.

Address should use a scheme prefix and be formatted like `tcp://192.168.0.10:9851` or `unix://socket`. Valid network schemes:

tcp   - bind to both IPv4 and IPv6
tcp4  - IPv4
tcp6  - IPv6
udp   - bind to both IPv4 and IPv6
udp4  - IPv4
udp6  - IPv6
unix  - Unix Domain Socket

The "tcp" network scheme is assumed when one is not specified.

func Stop

func Stop(ctx context.Context, protoAddr string) error

Stop gracefully shuts down the server without interrupting any active eventloops, it waits indefinitely for connections and eventloops to be closed and then shuts down.

Types

type Action

type Action int

Action is an action that occurs after the completion of an event.

const (
	// None indicates that no action should occur following an event.
	None Action = iota

	// Close closes the connection.
	Close

	// Shutdown shutdowns the server.
	Shutdown
)

type BuiltInFrameCodec

type BuiltInFrameCodec struct {
}

BuiltInFrameCodec is the built-in codec which will be assigned to gnet server when customized codec is not set up.

func (*BuiltInFrameCodec) Decode

func (cc *BuiltInFrameCodec) Decode(c Conn) ([]byte, error)

Decode ...

func (*BuiltInFrameCodec) Encode

func (cc *BuiltInFrameCodec) Encode(c Conn, buf []byte) ([]byte, error)

Encode ...

type Conn

type Conn interface {
	// Context returns a user-defined context.
	Context() (ctx interface{})

	// SetContext sets a user-defined context.
	SetContext(ctx interface{})

	// LocalAddr is the connection's local socket address.
	LocalAddr() (addr net.Addr)

	// RemoteAddr is the connection's remote peer address.
	RemoteAddr() (addr net.Addr)

	// Read reads all data from inbound ring-buffer and event-loop-buffer without moving "read" pointer, which means
	// it does not evict the data from buffers actually and those data will present in buffers until the
	// ResetBuffer method is called.
	Read() (buf []byte)

	// ResetBuffer resets the buffers, which means all data in inbound ring-buffer and event-loop-buffer will be evicted.
	ResetBuffer()

	// ReadN reads bytes with the given length from inbound ring-buffer and event-loop-buffer without moving
	// "read" pointer, which means it will not evict the data from buffers until the ShiftN method is called,
	// it reads data from the inbound ring-buffer and event-loop-buffer and returns both bytes and the size of it.
	// If the length of the available data is less than the given "n", ReadN will return all available data, so you
	// should make use of the variable "size" returned by it to be aware of the exact length of the returned data.
	ReadN(n int) (size int, buf []byte)

	// ShiftN shifts "read" pointer in the internal buffers with the given length.
	ShiftN(n int) (size int)

	// BufferLength returns the length of available data in the internal buffers.
	BufferLength() (size int)

	// SendTo writes data for UDP sockets, it allows you to send data back to UDP socket in individual goroutines.
	SendTo(buf []byte) error

	// AsyncWrite writes data to client/connection asynchronously, usually you would call it in individual goroutines
	// instead of the event-loop goroutines.
	AsyncWrite(buf []byte) error

	// Wake triggers a React event for this connection.
	Wake() error

	// Close closes the current connection.
	Close() error
}

Conn is a interface of gnet connection.

type DecoderConfig

type DecoderConfig struct {
	// ByteOrder is the ByteOrder of the length field.
	ByteOrder binary.ByteOrder
	// LengthFieldOffset is the offset of the length field
	LengthFieldOffset int
	// LengthFieldLength is the length of the length field
	LengthFieldLength int
	// LengthAdjustment is the compensation value to add to the value of the length field
	LengthAdjustment int
	// InitialBytesToStrip is the number of first bytes to strip out from the decoded frame
	InitialBytesToStrip int
}

DecoderConfig config for decoder.

type DelimiterBasedFrameCodec

type DelimiterBasedFrameCodec struct {
	// contains filtered or unexported fields
}

DelimiterBasedFrameCodec encodes/decodes specific-delimiter-separated frames into/from TCP stream.

func NewDelimiterBasedFrameCodec

func NewDelimiterBasedFrameCodec(delimiter byte) *DelimiterBasedFrameCodec

NewDelimiterBasedFrameCodec instantiates and returns a codec with a specific delimiter.

func (*DelimiterBasedFrameCodec) Decode

func (cc *DelimiterBasedFrameCodec) Decode(c Conn) ([]byte, error)

Decode ...

func (*DelimiterBasedFrameCodec) Encode

func (cc *DelimiterBasedFrameCodec) Encode(c Conn, buf []byte) ([]byte, error)

Encode ...

type EncoderConfig

type EncoderConfig struct {
	// ByteOrder is the ByteOrder of the length field.
	ByteOrder binary.ByteOrder
	// LengthFieldLength is the length of the length field.
	LengthFieldLength int
	// LengthAdjustment is the compensation value to add to the value of the length field
	LengthAdjustment int
	// LengthIncludesLengthFieldLength is true, the length of the prepended length field is added to the value of
	// the prepended length field
	LengthIncludesLengthFieldLength bool
}

EncoderConfig config for encoder.

type EventHandler

type EventHandler interface {
	// OnInitComplete fires when the server is ready for accepting connections.
	// The parameter:server has information and various utilities.
	OnInitComplete(server Server) (action Action)

	// OnShutdown fires when the server is being shut down, it is called right after
	// all event-loops and connections are closed.
	OnShutdown(server Server)

	// OnOpened fires when a new connection has been opened.
	// The parameter:c has information about the connection such as it's local and remote address.
	// Parameter:out is the return value which is going to be sent back to the client.
	OnOpened(c Conn) (out []byte, action Action)

	// OnClosed fires when a connection has been closed.
	// The parameter:err is the last known connection error.
	OnClosed(c Conn, err error) (action Action)

	// PreWrite fires just before any data is written to any client socket, this event function is usually used to
	// put some code of logging/counting/reporting or any prepositive operations before writing data to client.
	PreWrite()

	// React fires when a connection sends the server data.
	// Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client.
	// Parameter:out is the return value which is going to be sent back to the client.
	React(frame []byte, c Conn) (out []byte, action Action)

	// Tick fires immediately after the server starts and will fire again
	// following the duration specified by the delay return value.
	Tick() (delay time.Duration, action Action)
}

EventHandler represents the server events' callbacks for the Serve call. Each event has an Action return value that is used manage the state of the connection and server.

type EventServer

type EventServer struct {
}

EventServer is a built-in implementation of EventHandler which sets up each method with a default implementation, you can compose it with your own implementation of EventHandler when you don't want to implement all methods in EventHandler.

func (*EventServer) OnClosed

func (es *EventServer) OnClosed(c Conn, err error) (action Action)

OnClosed fires when a connection has been closed. The parameter:err is the last known connection error.

func (*EventServer) OnInitComplete

func (es *EventServer) OnInitComplete(svr Server) (action Action)

OnInitComplete fires when the server is ready for accepting connections. The parameter:server has information and various utilities.

func (*EventServer) OnOpened

func (es *EventServer) OnOpened(c Conn) (out []byte, action Action)

OnOpened fires when a new connection has been opened. The parameter:c has information about the connection such as it's local and remote address. Parameter:out is the return value which is going to be sent back to the client.

func (*EventServer) OnShutdown

func (es *EventServer) OnShutdown(svr Server)

OnShutdown fires when the server is being shut down, it is called right after all event-loops and connections are closed.

func (*EventServer) PreWrite

func (es *EventServer) PreWrite()

PreWrite fires just before any data is written to any client socket, this event function is usually used to put some code of logging/counting/reporting or any prepositive operations before writing data to client.

func (*EventServer) React

func (es *EventServer) React(frame []byte, c Conn) (out []byte, action Action)

React fires when a connection sends the server data. Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client. Parameter:out is the return value which is going to be sent back to the client.

func (*EventServer) Tick

func (es *EventServer) Tick() (delay time.Duration, action Action)

Tick fires immediately after the server starts and will fire again following the duration specified by the delay return value.

type FixedLengthFrameCodec

type FixedLengthFrameCodec struct {
	// contains filtered or unexported fields
}

FixedLengthFrameCodec encodes/decodes fixed-length-separated frames into/from TCP stream.

func NewFixedLengthFrameCodec

func NewFixedLengthFrameCodec(frameLength int) *FixedLengthFrameCodec

NewFixedLengthFrameCodec instantiates and returns a codec with fixed length.

func (*FixedLengthFrameCodec) Decode

func (cc *FixedLengthFrameCodec) Decode(c Conn) ([]byte, error)

Decode ...

func (*FixedLengthFrameCodec) Encode

func (cc *FixedLengthFrameCodec) Encode(c Conn, buf []byte) ([]byte, error)

Encode ...

type ICodec

type ICodec interface {
	// Encode encodes frames upon server responses into TCP stream.
	Encode(c Conn, buf []byte) ([]byte, error)
	// Decode decodes frames from TCP stream via specific implementation.
	Decode(c Conn) ([]byte, error)
}

ICodec is the interface of gnet codec.

type LengthFieldBasedFrameCodec

type LengthFieldBasedFrameCodec struct {
	// contains filtered or unexported fields
}

LengthFieldBasedFrameCodec is the refactoring from https://github.com/smallnest/goframe/blob/master/length_field_based_frameconn.go, licensed by Apache License 2.0. It encodes/decodes frames into/from TCP stream with value of the length field in the message.

func NewLengthFieldBasedFrameCodec

func NewLengthFieldBasedFrameCodec(ec EncoderConfig, dc DecoderConfig) *LengthFieldBasedFrameCodec

NewLengthFieldBasedFrameCodec instantiates and returns a codec based on the length field. It is the go implementation of netty LengthFieldBasedFrameecoder and LengthFieldPrepender. you can see javadoc of them to learn more details.

func (*LengthFieldBasedFrameCodec) Decode

func (cc *LengthFieldBasedFrameCodec) Decode(c Conn) ([]byte, error)

Decode ...

func (*LengthFieldBasedFrameCodec) Encode

func (cc *LengthFieldBasedFrameCodec) Encode(c Conn, buf []byte) (out []byte, err error)

Encode ...

type LineBasedFrameCodec

type LineBasedFrameCodec struct {
}

LineBasedFrameCodec encodes/decodes line-separated frames into/from TCP stream.

func (*LineBasedFrameCodec) Decode

func (cc *LineBasedFrameCodec) Decode(c Conn) ([]byte, error)

Decode ...

func (*LineBasedFrameCodec) Encode

func (cc *LineBasedFrameCodec) Encode(c Conn, buf []byte) ([]byte, error)

Encode ...

type LoadBalancing

type LoadBalancing int

LoadBalancing represents the the type of load-balancing algorithm.

const (
	// RoundRobin assigns the next accepted connection to the event-loop by polling event-loop list.
	RoundRobin LoadBalancing = iota

	// LeastConnections assigns the next accepted connection to the event-loop that is
	// serving the least number of active connections at the current time.
	LeastConnections

	// SourceAddrHash assignes the next accepted connection to the event-loop by hashing the remote address.
	SourceAddrHash
)

type Option

type Option func(opts *Options)

Option is a function that will set up option.

func WithCodec

func WithCodec(codec ICodec) Option

WithCodec sets up a codec to handle TCP stream.

func WithLoadBalancing

func WithLoadBalancing(lb LoadBalancing) Option

WithLoadBalancing sets up the load-balancing algorithm in gnet server.

func WithLockOSThread

func WithLockOSThread(lockOSThread bool) Option

WithLockOSThread sets up lockOSThread mode for I/O event-loops.

func WithLogger

func WithLogger(logger logging.Logger) Option

WithLogger sets up a customized logger.

func WithMulticore

func WithMulticore(multicore bool) Option

WithMulticore sets up multi-cores in gnet server.

func WithNumEventLoop

func WithNumEventLoop(numEventLoop int) Option

WithNumEventLoop sets up NumEventLoop in gnet server.

func WithOptions

func WithOptions(options Options) Option

WithOptions sets up all options.

func WithReusePort

func WithReusePort(reusePort bool) Option

WithReusePort sets up SO_REUSEPORT socket option.

func WithTCPKeepAlive

func WithTCPKeepAlive(tcpKeepAlive time.Duration) Option

WithTCPKeepAlive sets up SO_KEEPALIVE socket option.

func WithTicker

func WithTicker(ticker bool) Option

WithTicker indicates that a ticker is set.

type Options

type Options struct {
	// Multicore indicates whether the server will be effectively created with multi-cores, if so,
	// then you must take care with synchronizing memory between all event callbacks, otherwise,
	// it will run the server with single thread. The number of threads in the server will be automatically
	// assigned to the value of logical CPUs usable by the current process.
	Multicore bool

	// LockOSThread is used to determine whether each I/O event-loop is associated to an OS thread, it is useful when you
	// need some kind of mechanisms like thread local storage, or invoke certain C libraries (such as graphics lib: GLib)
	// that require thread-level manipulation via cgo, or want all I/O event-loops to actually run in parallel for a
	// potential higher performance.
	LockOSThread bool

	// LB represents the load-balancing algorithm used when assigning new connections.
	LB LoadBalancing

	// NumEventLoop is set up to start the given number of event-loop goroutine.
	// Note: Setting up NumEventLoop will override Multicore.
	NumEventLoop int

	// ReusePort indicates whether to set up the SO_REUSEPORT socket option.
	ReusePort bool

	// Ticker indicates whether the ticker has been set up.
	Ticker bool

	// TCPKeepAlive sets up a duration for (SO_KEEPALIVE) socket option.
	TCPKeepAlive time.Duration

	// ICodec encodes and decodes TCP stream.
	Codec ICodec

	// Logger is the customized logger for logging info, if it is not set,
	// then gnet will use the default logger powered by go.uber.org/zap.
	Logger logging.Logger
}

Options are set when the client opens.

type Server

type Server struct {

	// Multicore indicates whether the server will be effectively created with multi-cores, if so,
	// then you must take care of synchronizing the shared data between all event callbacks, otherwise,
	// it will run the server with single thread. The number of threads in the server will be automatically
	// assigned to the value of logical CPUs usable by the current process.
	Multicore bool

	// The Addr parameter is the listening address that align
	// with the addr string passed to the Serve function.
	Addr net.Addr

	// NumEventLoop is the number of event-loops that the server is using.
	NumEventLoop int

	// ReusePort indicates whether SO_REUSEPORT is enable.
	ReusePort bool

	// TCPKeepAlive (SO_KEEPALIVE) socket option.
	TCPKeepAlive time.Duration
	// contains filtered or unexported fields
}

Server represents a server context which provides information about the running server and has control functions for managing state.

func (Server) CountConnections

func (s Server) CountConnections() (count int)

CountConnections counts the number of currently active connections and returns it.

func (Server) DupFd

func (s Server) DupFd() (dupFD int, err error)

DupFd returns a copy of the underlying file descriptor of listener. It is the caller's responsibility to close dupFD when finished. Closing listener does not affect dupFD, and closing dupFD does not affect listener.