golang游戏服务器框架插件库gonet的使用

golang游戏服务器框架插件库gonet的使用

架构概述

gonet是一个用Golang实现的游戏服务器框架,其架构如下图所示:

Architecture

服务器组件

Game Server(GS)

  • 玩家直接连接GS,处理玩家逻辑
  • 与HUB/SS通信
  • 可以存在若干个GS实例

Hub Server(HUB)

  • 若干个GS连接到一个HUB
  • 只存在一个HUB实例
  • 维护基础的全局信息
  • 处理GS之间的消息转发

Stats Server(SS)

  • 统计服务器,记录玩家行为数据
  • 用于后期统计分析
  • 数据量较大,性能需求不同,故单独部署

通信原则

  1. GS到HUB/SS的通信都是Call同步调用,GS必须等待ACK
  2. HUB到GS的通信只有forward数据包
  3. 单播消息在玩家离线时会存入db,登录后GS直接读取db并forward给玩家goroutine(持久化)
  4. 多播消息会发送给所有的在线玩家(非持久化)
  5. 广播消息会发送给所有的在线玩家(非持久化)

服务器状态一致性

  1. GS节点可以单独重启
  2. HUB重启后,GS必须全部重启
  3. SS可随意重启,不影响业务

安装先决条件

  1. 确保安装好graphviz, gawk
  2. 确保安装好mongodb
  3. 确保config.ini中的mongo_xxxx配置正确
  4. 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: 服务单元,相当于actor
  • Module: 功能模块,可插拔的组件
  • 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. 最佳实践

  1. 消息设计:使用protobuf定义消息结构
  2. 错误处理:统一错误码和错误处理
  3. 日志记录:集成zap等高性能日志库
  4. 配置管理:使用viper管理配置
  5. 压力测试:使用vegeta进行负载测试

6. 性能调优

  1. 调整协程池大小
  2. 优化消息序列化
  3. 使用对象池减少GC压力
  4. 监控关键指标:消息延迟、队列长度等

gonet是一个轻量但功能完善的游戏服务器框架,适合中小型游戏项目。它的设计简洁,扩展性强,可以快速构建高性能的游戏服务器。

回到顶部