咱们最开始作的游戏框架,多数都是client—>server—>db的模式,可是随着玩家数量的增长,一个server进程就会扛不住,须要多个进程服务于多个玩家。可是给定了不一样进程的玩家,有可能须要交互,这就致使了client与server端的链接,有多是o(1),但也多是o(n)链接,o(n)的扩展性很是差,不容易维护,所以能够剔除了。可是若是只保持o(1),那必然要引入新的抽象服务,网关也就登场了。下图是一个简单的网关部署架构:

网关的引入,有哪些改变呢?
- 内外网解耦,在保持客外网客户端不变的状况下,能够经过这个中间层调整内网服务的实现
- 规范化,因为请求是网关统一接受和分发的,会直接促使客户端在发送和接受请求时规范化
- 安全,因为网关具备收口做用,全部的安全问题均可以在这里解决,保护内网,好比反爬,认证等功能
- 限流熔断,在网关上实现限流,避免内网被突发流量压垮
- 统一的监控告警平台
有了网关后,开始在下游增长业务逻辑,可能咱们会把全部的业务都耦合成一个service,好比聊天挂了,派系挂了,场景挂了,均可能会对有戏自己产生影响;基于此,不得不考虑拆分进程,以前的游戏service服务,可能会被拆分为多个服务,可是对于大多数的游戏开发人员来讲,基于服务的开发,比基于进程的开发,也难的多,若是不是领导推动,也不会有人愿意把聊天作成一个单独的服务。
对于游戏来讲,服务拆分最最极端的状况,就是一个消息cmd对应了一个service,可是这种状况会致使service愈来愈多,没法维护的程度,实际上游戏拆分也确实没有必要。不过服务service愈来愈多,某个service甚至处于内存,cpu瓶颈的状态,应该如何解决呢?这时候rpc的服务治理派上了用场。咱们对上面的图示作下改动:

game-rpc的引入,解决了哪些问题呢?
- 开发人员再也不须要关注内部通讯机制,减小项目开发时间,下降成本
- 强大的集群容错,负载均衡能力等,保证每次调用都能路由到合适的节点
service与service作成了集群,每一个service启动后,往zk或nacos注册中心注册本身的url。gateway在启动后,订阅zk注册中心的service列表,依托于rpc自己强大的集群,负载等功能,能够自动实现service的切换。
在针对rpg等长链接游戏类型时,玩家在场景中的移动都须要同步,广播给周围的玩家,可是rpc是单通道的,不能回传,这应该如何处理呢?
有借于此,game-rpc增长了全双工的概念,不只仅是client对service的请求,同时service也能够根据uniqueId,进行主动推送。因而上面的流程图变成了下面这样:
一切看上去都很完美,彷佛没有问题了,然而新的问题随之出现。
咱们知道,优秀的架构体系中,单点问题是不能容忍的,很不幸,咱们的gateway,就出现了单点。随着玩家数量的增长,整个服务都会处于不可用的状态。因而网关须要拆成集群的模式,新的架构图显示以下:
网关拆分后,gate1和gate2的玩家是两个tcp长连状态的服务,没法交互,这应该怎么办?
咱们参照了现行市面上比较经常使用的tcp网关作法,消息下行通知的解决方案,目前框架支持了两种方式:
- MQ广播机制,当某台网关服务器收到广播消息后,MQ通知给集群内的全部gate server,每一个gate在收到消息后,判断要推送端的消息是不是当前gate所持有的会话,若是在当前服务,则进行推送,不然抛弃
- redis session共享,针对MQ的广播机制,若是之后游戏火爆,同时有百万玩家在线,那么gate集群里的机器,可能会达到上百台不等,若是每一个消息都须要MQ广播,有可能会致使信号风暴,因而咱们调整了最后一种解决方案。玩家在登陆网关,认证成功后,把玩家id做为key,当前链接的网关uniqueId做为value,存储到redis集群中。网关随后把消息路由到具体某个service,service从redis集群里获取到须要广播的玩家对应的gate服务,service经过rpc消息下行,直接推送到具体的gate,再由gate转发到client
说明:这种架构,更适用于全区全服类型的游戏。目前咱们已经有多款线上游戏使用。
更多交流,也欢迎您关注个人微信公众号: