Lightweight, facility, high performance golang based game server framework
Switch branches/tags
Nothing to show
Clone or download
Latest commit 860021a Sep 19, 2018
Permalink
Failed to load latest commit information.
benchmark fixed benchmark May 17, 2018
component feature: override service route Sep 29, 2017
docs fixed benchmark May 17, 2018
examples/demo refactor session lifetime handler Aug 14, 2018
internal more comments Aug 17, 2017
serialize Update protobuf.go Aug 20, 2017
service more comments Aug 17, 2017
session refactor session lifetime handler Aug 14, 2018
.gitignore fixed benchmark May 17, 2018
.travis.yml Update .travis.yml Sep 19, 2018
LICENSE fixed benchmark May 17, 2018
README.md commit Sep 19, 2018
agent.go improve error log Sep 14, 2018
app.go SIGTERM Sep 4, 2018
application.png commit Oct 2, 2017
component.go feature: override service route Sep 29, 2017
config.go refactor session lifetime handler Aug 14, 2018
const.go init commit Aug 2, 2017
errors.go docs: message related Aug 9, 2017
group.go log: detail information Sep 5, 2017
group_test.go add more comments & fix typo Aug 15, 2017
handler.go refactor session lifetime handler Aug 14, 2018
handler_test.go fixed benchmark May 17, 2018
interface.go refactor session lifetime handler Aug 14, 2018
invoke.go feature: invoke function in main logic goroutine Oct 30, 2017
logger.go fix typo & more comments to make golint happy Aug 15, 2017
options.go fixed benchmark May 17, 2018
pipeline.go demo fixed Jul 7, 2018
serialize.go comment Aug 8, 2017
timer.go feature: invoke function in main logic goroutine Oct 30, 2017
utils.go refactor: redesign interface Aug 5, 2017
utils_test.go benchmark: empty map traverse Aug 15, 2017
ws.go feature: allows the use of custom Logger Aug 11, 2017

README.md

Nano Build Status GoDoc Go Report Card MIT licensed

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.

Application

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 or consul in nano 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

Resources

Community

Successful cases

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

MIT License