golang游戏服务器框架插件库gonet的使用
golang游戏服务器框架插件库gonet的使用
架构概述
gonet是一个用Golang实现的游戏服务器框架,其架构如下图所示:
服务器组件
Game Server(GS)
- 玩家直接连接GS,处理玩家逻辑
- 与HUB/SS通信
- 可以存在若干个GS实例
Hub Server(HUB)
- 若干个GS连接到一个HUB
- 只存在一个HUB实例
- 维护基础的全局信息
- 处理GS之间的消息转发
Stats Server(SS)
- 统计服务器,记录玩家行为数据
- 用于后期统计分析
- 数据量较大,性能需求不同,故单独部署
通信原则
- GS到HUB/SS的通信都是Call同步调用,GS必须等待ACK
- HUB到GS的通信只有forward数据包
- 单播消息在玩家离线时会存入db,登录后GS直接读取db并forward给玩家goroutine(持久化)
- 多播消息会发送给所有的在线玩家(非持久化)
- 广播消息会发送给所有的在线玩家(非持久化)
服务器状态一致性
- GS节点可以单独重启
- HUB重启后,GS必须全部重启
- SS可随意重启,不影响业务
安装先决条件
- 确保安装好graphviz, gawk
- 确保安装好mongodb
- 确保config.ini中的mongo_xxxx配置正确
- export GOPATH=‘当前目录’
安装步骤
git clone https://github.com/xtaci/gonet
cd gonet
export GOPATH=~/gonet
go get gopkg.in/mgo.v2
make
./start-test.sh
示例代码
以下是一个简单的GS服务器示例代码:
package main
import (
"github.com/xtaci/gonet"
"log"
)
// 游戏服务器结构体
type GameServer struct {
*gonet.TCPServer
}
// 处理新连接
func (gs *GameServer) OnConnect(c *gonet.TCPConn) {
log.Println("New client connected:", c.GetRemoteAddr())
}
// 处理断开连接
func (gs *GameServer) OnClose(c *gonet.TCPConn) {
log.Println("Client disconnected:", c.GetRemoteAddr())
}
// 处理消息
func (gs *GameServer) OnMessage(c *gonet.TCPConn, p gonet.Packet) {
log.Printf("Received message from %s: %v\n", c.GetRemoteAddr(), p)
// 简单回显消息
if err := c.AsyncWritePacket(p, 0); err != nil {
log.Println("Write error:", err)
}
}
func main() {
// 创建游戏服务器
gs := &GameServer{
TCPServer: gonet.NewTCPServer(),
}
// 设置回调函数
gs.SetOnConnectCallback(gs.OnConnect)
gs.SetOnCloseCallback(gs.OnClose)
gs.SetOnMsgCallback(gs.OnMessage)
// 启动服务器
if err := gs.Start(":8080"); err != nil {
log.Fatal("Failed to start server:", err)
}
log.Println("Game server started on :8080")
// 等待服务器关闭
gs.Wait()
}
与HUB通信示例
package main
import (
"github.com/xtaci/gonet"
"log"
"time"
)
func main() {
// 连接到HUB服务器
hubConn, err := gonet.Dial("hub.example.com:9090")
if err != nil {
log.Fatal("Failed to connect to HUB:", err)
}
defer hubConn.Close()
log.Println("Connected to HUB server")
// 发送消息到HUB
msg := gonet.NewPacket(1, []byte("Hello HUB!"))
if err := hubConn.AsyncWritePacket(msg, 0); err != nil {
log.Println("Failed to send message to HUB:", err)
}
// 接收HUB响应
go func() {
for {
p, err := hubConn.ReadPacket()
if err != nil {
log.Println("Error reading from HUB:", err)
return
}
log.Printf("Received message from HUB: %v\n", p)
}
}()
// 保持连接
for {
time.Sleep(1 * time.Second)
}
}
注意:gonet1已停止维护,建议移步至新架构gonet2。
更多关于golang游戏服务器框架插件库gonet的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang游戏服务器框架插件库gonet的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
gonet游戏服务器框架插件库使用指南
gonet是一个轻量级的Go语言游戏服务器框架,提供了网络通信、协程管理、定时器等游戏服务器常用功能。下面我将详细介绍gonet的核心功能和使用方法。
1. 基本架构
gonet采用actor模型,主要包含以下组件:
Service
: 服务单元,相当于actorModule
: 功能模块,可插拔的组件RPC
: 远程调用机制Timer
: 定时器
2. 快速开始
安装
go get github.com/gonet2/...
简单示例
package main
import (
"github.com/gonet2/sn"
"log"
)
func main() {
// 创建服务
service := sn.NewService("testService")
// 注册处理函数
service.RegisterHandler("echo", func(ctx *sn.Context) {
msg := ctx.GetMsg()
log.Printf("Received: %s", msg.Body)
ctx.Reply(msg.Body)
})
// 启动服务
if err := service.Start(); err != nil {
log.Fatal(err)
}
// 等待服务结束
service.Wait()
}
3. 核心功能详解
3.1 服务(Service)管理
// 创建服务
service := sn.NewService("gameServer",
sn.WithMaxQueueSize(10000), // 设置消息队列大小
sn.WithPoolSize(100), // 设置协程池大小
)
// 启动服务
if err := service.Start(); err != nil {
log.Fatal(err)
}
// 停止服务
service.Stop()
3.2 消息处理
// 注册消息处理器
service.RegisterHandler("player.login", func(ctx *sn.Context) {
// 解析消息
var loginReq LoginRequest
if err := json.Unmarshal(ctx.GetMsg().Body, &loginReq); err != nil {
ctx.ReplyError(err)
return
}
// 处理逻辑
player := NewPlayer(loginReq.UserID)
// 响应
ctx.Reply(LoginResponse{Success: true})
})
// 发送消息
msg := &sn.Message{
To: "playerService",
Topic: "player.move",
Body: []byte(`{"x":100, "y":200}`),
}
service.Send(msg)
3.3 RPC调用
// 定义RPC接口
type PlayerService interface {
GetPlayerInfo(userID int64) (*PlayerInfo, error)
}
// 注册RPC服务
service.RegisterRPC(new(PlayerService), func(userID int64) (*PlayerInfo, error) {
// 实现逻辑
return &PlayerInfo{Name: "test"}, nil
})
// 调用RPC
client := sn.NewRPCClient("playerService")
var playerService PlayerService
client.ConvertTo(&playerService)
info, err := playerService.GetPlayerInfo(123)
3.4 定时器
// 注册定时任务
service.AddTimer(5*time.Second, func() {
log.Println("定时任务执行")
})
// 一次性定时器
service.AddOnceTimer(10*time.Second, func() {
log.Println("一次性定时任务")
})
4. 高级特性
4.1 模块系统
// 定义模块
type BattleModule struct {
sn.BaseModule
}
func (m *BattleModule) OnStart() {
log.Println("BattleModule started")
}
func (m *BattleModule) OnStop() {
log.Println("BattleModule stopped")
}
// 注册模块
service.AddModule("battle", &BattleModule{})
4.2 集群支持
// 配置集群
config := cluster.DefaultConfig()
config.EtcdEndpoints = []string{"http://127.0.0.1:2379"}
cluster.Init(config)
// 服务发现
discovery := cluster.NewDiscovery("gameServers")
nodes := discovery.GetNodes()
4.3 性能监控
// 启用性能监控
monitor := sn.NewMonitor(service)
monitor.Start()
// 自定义监控指标
monitor.AddGauge("player_count", func() float64 {
return float64(playerManager.Count())
})
5. 最佳实践
- 消息设计:使用protobuf定义消息结构
- 错误处理:统一错误码和错误处理
- 日志记录:集成zap等高性能日志库
- 配置管理:使用viper管理配置
- 压力测试:使用vegeta进行负载测试
6. 性能调优
- 调整协程池大小
- 优化消息序列化
- 使用对象池减少GC压力
- 监控关键指标:消息延迟、队列长度等
gonet是一个轻量但功能完善的游戏服务器框架,适合中小型游戏项目。它的设计简洁,扩展性强,可以快速构建高性能的游戏服务器。