README
Nano

Nano is an easy to use, fast, lightweight game server networking library for Go. It provides a core network architecture and a series of tools and libraries that can help developers eliminate boring duplicate work for common underlying logic. The goal of nano is to improve development efficiency by eliminating the need to spend time on repetitious network related programming.
Nano was designed for server-side applications like real-time games, social games, mobile games, etc of all sizes.
How to build a system with Nano
What does a Nano
application look like?
The simplest "nano" application as shown in the following figure, you can make powerful applications by combining different components.
In fact, the nano
application is a collection of Component , and a component is a bundle of Handler, once you register a component to nano, nano will register all methods that can be converted to Handler
to nano service container. Service was accessed by Component.Handler
, and the handler will be called while client request. The handler will receive two parameters while handling a message:
*session.Session
: corresponding a client that apply this request or notify.*protocol.FooBar
: the payload of the request.
While you had processed your logic, you can response or push message to the client by session.Response(payload)
and session.Push('eventName', payload)
, or returns error when some unexpected data received.
How to build distributed system with Nano
Nano has no built-in distributed system components, but you can easily implement it with gRPC
and smux
. Here we take grpc as an example.
- First of all, you need to define a remote component
type RemoteComponent struct {
rpcClients []*grpc.ClientConn
}
- Second, fetch all grpc servers infomation from services like
etcd
orconsul
innano
lifetime hooks
type ServerInfo struct {
Host string `json:"host"`
Port int `json:"port"`
}
// lifetime callback
func (r *RemoteComponent) Init() {
// fetch server list from etcd
resp, err := http.Get("http://your_etcd_server/backend/server_list/area/10023")
if err != nil {
panic(err)
}
servers := []ServerInfo{}
if err := json.NewDecoder(resp.Body).Decode(&servers); err != nil {
panic(err)
}
for i := range servers {
server := servers[i]
client, err := grpc.Dial(fmt.Sprintf("%s:%d", server.Host, server.Post), options)
if err != nil {
panic(err)
}
r.rpcClients = append(r.rpcClients, client)
}
}
func (r *RemoteComponent) client(s *session.Session) *grpc.ClientConn {
// load balance
return r.rpcClients[s.UID() % len(s.rpcClients)]
}
// Your handler, accessed by:
// nanoClient.Request("RemoteComponent.DemoHandler", &pb.DemoMsg{/*...*/})
func (r *RemoteComponent) DemoHandler(s *session.Session, msg *pb.DemoMsg) error {
client := r.client(s)
// do something with client
// ....
// ...
return nil
}
The Nano will remain simple, but you can perform any operations in the component and get the desired goals. You can startup a group of Nano
application as agent to dispatch message to backend servers.
How to execute the asynchronous task
func (manager *PlayerManager) Login(s *session.Session, msg *ReqPlayerLogin) error {
var onDBResult = func(player *Player) {
manager.players = append(manager.players, player)
s.Push("PlayerSystem.LoginSuccess", &ResPlayerLogin)
}
// run slow task in new gorontine
go func() {
player, err := db.QueryPlayer(msg.PlayerId) // ignore error in demo
// handle result in main logical gorontine
nano.Invoke(func(){ onDBResult(player) })
}
return nil
}
Documents
-
English
-
简体中文
Resources
-
Javascript
-
Demo
Community
Successful cases
Go version
> go1.8
Installation
go get github.com/lonnng/nano
# dependencies
go get -u github.com/golang/protobuf
go get -u github.com/gorilla/websocket
Benchmark
# Case: PingPong
# OS: Windows 10
# Device: i5-6500 3.2GHz 4 Core/1000-Concurrent => IOPS 11W(Average)
# Other: ...
cd $GOPATH/src/github.com/lonnng/nano/benchmark/io
go test -v -tags "benchmark"
License
Documentation
Index ¶
- Variables
- func EnableDebug()
- func Invoke(fn func())
- func Listen(addr string, opts ...Option)
- func ListenWS(addr string, opts ...Option)
- func Register(c component.Component, options ...component.Option)
- func SetCheckOriginFunc(fn func(*http.Request) bool)
- func SetDictionary(dict map[string]uint16)
- func SetHeartbeatInterval(d time.Duration)
- func SetLogger(l Logger)
- func SetSerializer(seri serialize.Serializer)
- func SetTimerPrecision(precision time.Duration)
- func SetWSPath(path string)
- func Shutdown()
- type Group
- func (c *Group) Add(session *session.Session) error
- func (c *Group) Broadcast(route string, v interface{}) error
- func (c *Group) Close() error
- func (c *Group) Contains(uid int64) bool
- func (c *Group) Count() int
- func (c *Group) Leave(s *session.Session) error
- func (c *Group) LeaveAll() error
- func (c *Group) Member(uid int64) (*session.Session, error)
- func (c *Group) Members() []int64
- func (c *Group) Multicast(route string, v interface{}, filter SessionFilter) error
- type Logger
- type Message
- type Option
- type Pipeline
- type PipelineChannel
- type PipelineFunc
- type SessionFilter
- type Timer
- type TimerCondition
- type TimerFunc
Constants ¶
Variables ¶
var ( // ErrBrokenPipe represents the low-level connection has broken. ErrBrokenPipe = errors.New("broken low-level pipe") // ErrBufferExceed indicates that the current session buffer is full and // can not receive more data. ErrBufferExceed = errors.New("session send buffer exceed") )
var ( ErrSessionOnNotify = errors.New("current session working on notify mode") ErrCloseClosedGroup = errors.New("close closed group") ErrClosedGroup = errors.New("group closed") ErrMemberNotFound = errors.New("member not found in the group") ErrCloseClosedSession = errors.New("close closed session") ErrSessionDuplication = errors.New("session has existed in the current group") )
Errors that could be occurred during message handling.
var VERSION = "0.0.1"
VERSION returns current nano version
Functions ¶
func Listen ¶
Listen listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections.
func ListenWS ¶
ListenWS listens on the TCP network address addr and then upgrades the HTTP server connection to the WebSocket protocol to handle requests on incoming connections.
func SetCheckOriginFunc ¶
SetCheckOriginFunc set the function that check `Origin` in http headers
func SetDictionary ¶
SetDictionary set routes map, TODO(warning): set dictionary in runtime would be a dangerous operation!!!!!!
func SetHeartbeatInterval ¶
SetHeartbeatInterval set heartbeat time interval
func SetSerializer ¶
func SetSerializer(seri serialize.Serializer)
SetSerializer customize application serializer, which automatically Marshal and UnMarshal handler payload
func SetTimerPrecision ¶
SetTimerPrecision set the ticker precision, and time precision can not less than a Millisecond, and can not change after application running. The default precision is time.Second
Types ¶
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
Group represents a session group which used to manage a number of sessions, data send to the group will send to all session in it.
type Logger ¶
type Logger interface { Println(v ...interface{}) Fatal(v ...interface{}) }
Logger represents the log interface
type Pipeline ¶
type Pipeline interface { Outbound() PipelineChannel Inbound() PipelineChannel }
func NewPipeline ¶
func NewPipeline() Pipeline
type PipelineChannel ¶
type PipelineChannel interface { PushFront(h PipelineFunc) PushBack(h PipelineFunc) Process(s *session.Session, msg Message) error }
type SessionFilter ¶
SessionFilter represents a filter which was used to filter session when Multicast, the session will receive the message while filter returns true.
type Timer ¶
type Timer struct {
// contains filtered or unexported fields
}
Timer represents a cron job
func NewAfterTimer ¶
NewAfterTimer returns a new Timer containing a function that will be called after duration that specified by the duration argument. The duration d must be greater than zero; if not, NewAfterTimer will panic. Stop the timer to release associated resources.
func NewCondTimer ¶
func NewCondTimer(condition TimerCondition, fn TimerFunc) *Timer
NewCondTimer returns a new Timer containing a function that will be called when condition satisfied that specified by the condition argument. The duration d must be greater than zero; if not, NewCondTimer will panic. Stop the timer to release associated resources.
func NewCountTimer ¶
NewCountTimer returns a new Timer containing a function that will be called with a period specified by the duration argument. After count times, timer will be stopped automatically, It adjusts the intervals for slow receivers. The duration d must be greater than zero; if not, NewCountTimer will panic. Stop the timer to release associated resources.
func NewTimer ¶
NewTimer returns a new Timer containing a function that will be called with a period specified by the duration argument. It adjusts the intervals for slow receivers. The duration d must be greater than zero; if not, NewTimer will panic. Stop the timer to release associated resources.
type TimerCondition ¶
TimerCondition represents a checker that returns true when cron job needs to execute
Source Files
Directories
Path | Synopsis |
---|---|
benchmark
|
|
examples
|
|
internal
|
|