美文网首页go
基于消息队列的golang游戏服务器框架goserver

基于消息队列的golang游戏服务器框架goserver

作者: 小风吹的我乱了 | 来源:发表于2019-07-29 22:22 被阅读0次

    Git地址:https://github.com/0990/goserver
    作者一直想搭建一个自己的游戏服务器架构,近来有时间就开始着手,要求有以下两点:
    1,支持protobuf,websocket,因为本人从事过cocos creator客户端,基本目标就是和cocos creator的客户端能正常通信
    2,服务器架构支持分布式,这样可以支持横向扩展

    一般分布式游戏服务有网关服务器、游戏服务器、中心服务器基本要素,这里也不例外,网关服务器负责建议和维护客户端的通信,转发消息到其它服务器;游戏服务器负责游戏逻辑,压力大时可多开,中心服务器负责维护所有游戏状态和玩家状态

    1,网关服:
    网关服务器和客户端通信使用gorilla websocket,这样可以直接对接cocos creator,
    通信格式如下:
    -------------------------
    | id | protobuf message |
    -------------------------
    id是protobuf消息名字的hash值,用于反解析数据,目前未加入加密
    网关服主要作用是转发消息到其它服,常用接口

    g.RouteSessionMsg((*pb.ReqHello)(nil), BServerID)
    

    对于收到此消息的服务器请求,需要注册处理事件:

    s.RegisterSessionMsgHandler(func(client rpc.Session, req *pb.ReqHello) {
        resp := &pb.RespHello{Name:"回复您的请求"}
        client.SendMsg(resp)
    })
    

    2,服务器之间通信
    一般来说服务间通信有notify(只发送消息),request请求,call请求,request和call区别在于,call请求后会阻塞当前线程,等到返回消息到来或超时,才会继续,而request不会
    服务器之间的rpc有多种方式可以实现,我选择消息队列nats作为一个尝试,nats是高性能的消息队列服务,常用接口是publish(发布)和subscribe(订阅),在goserver中,每个服务器都订阅自己的服务器消息,A向B发消息就publish(B,msgData),B回A消息就publish(A,msgData),这样就构成了基础的rpc服务
    常用接口

    //向B服务器发送消息
    g.GetServerById(BServerID).Notify(&pb.ReqSend{Name:"我是send消息"})
    
    //向B服务器发送request请求
    g.GetServerById(BServerID).Request(&pb.ReqRequest{
        Name:"我是request请求",
    }, func(resp *pb.RespRequest,err error) {
        if err != nil {
            return
        }
        fmt.Println("返回消息:",resp.Name)
    })
    
    //向B服务器发送call请求
    resp := pb.RespCall{}
    err = g.GetServerById(BServerID).Call(&pb.ReqCall{Name:"我是call请求"}, &resp)
    if err != nil {
        return
    }
    fmt.Println("返回消息:",resp.Name)
    

    对于send,request和call请求,B服务器需要注册事件处理

    //注册send事件handler
    s.RegisterServerHandler(func(server rpc.Server, req *pb.ReqSend) {
        fmt.Println("收到消息:", req.Name)
    })
    
    //注册request事件handler
    s.RegisterRequestMsgHandler(func(server rpc.RequestServer, req *pb.ReqRequest) {
        resp := &pb.RespRequest{Name:"我是request返回消息"}
        server.Answer(resp)
    })
    
    //注册call事件handler
    s.RegisterRequestMsgHandler(func(server rpc.RequestServer, req *pb.ReqCall) {
        resp := &pb.RespCall{Name:"我是call返回消息"}
        server.Answer(resp)
    })
    

    具体使用方法见example目录下的示例

    基于goserver的对战小游戏: http://af.09900990.xyz:5050
    小游戏git地址: https://github.com/0990/avatar-fight-server

    相关文章

      网友评论

        本文标题:基于消息队列的golang游戏服务器框架goserver

        本文链接:https://www.haomeiwen.com/subject/fnwirctx.html