RPC服务在游戏中的简单运用

作者:二周目赤
出处:
【RPC服务在游戏中的简单运用】我们最开始做的游戏框架 , 多数都是client—>server—>db的模式 , 但是随着玩家数量的增加 , 一个server进程就会扛不住 , 需要多个进程服务于多个玩家 。 但是给定了不同进程的玩家 , 有可能需要交互 , 这就导致了client与server端的连接 , 有可能是o(1) , 但也可能是o(n)连接 , o(n)的扩展性非常差 , 不容易维护 , 因此可以剔除了 。 但是如果只保持o(1) , 那必然要引入新的抽象服务 , 网关也就登场了 。 下图是一个简单的网关部署架构:
RPC服务在游戏中的简单运用文章插图
网关的引入 , 有哪些改变呢?

  • 内外网解耦 , 在保持客外网客户端不变的情况下 , 可以通过这个中间层调整内网服务的实现
  • 规范化 , 由于请求是网关统一接受和分发的 , 会直接促使客户端在发送和接受请求时规范化
  • 安全 , 由于网关具有收口作用 , 所有的安全问题都可以在这里解决 , 保护内网 , 比如反爬 , 认证等功能
  • 限流熔断 , 在网关上实现限流 , 避免内网被突发流量压垮
  • 统一的监控告警平台
有了网关后 , 开始在下游增加业务逻辑 , 可能我们会把所有的业务都耦合成一个service , 比如聊天挂了 , 派系挂了 , 场景挂了 , 都可能会对有戏本身产生影响;基于此 , 不得不考虑拆分进程 , 之前的游戏service服务 , 可能会被拆分为多个服务 , 但是对于大多数的游戏开发人员来说 , 基于服务的开发 , 比基于进程的开发 , 也难的多 , 如果不是领导推进 , 也不会有人愿意把聊天做成一个单独的服务 。
对于游戏来说 , 服务拆分最最极端的情况 , 就是一个消息cmd对应了一个service , 但是这种情况会导致service越来越多 , 无法维护的程度 , 实际上游戏拆分也确实没有必要 。 不过服务service越来越多 , 某个service甚至处于内存 , cpu瓶颈的状态 , 应该如何解决呢?这时候rpc的服务治理派上了用场 。 我们对上面的图示做下改动:
RPC服务在游戏中的简单运用文章插图
game-rpc的引入 , 解决了哪些问题呢?
  • 开发人员不再需要关注内部通信机制 , 减少项目开发时间 , 降低成本
  • 强大的集群容错 , 负载均衡能力等 , 保证每次调用都能路由到合适的节点
service与service做成了集群 , 每个service启动后 , 往zk或nacos注册中心注册自己的url 。 gateway在启动后 , 订阅zk注册中心的service列表 , 依托于rpc本身强大的集群 , 负载等功能 , 可以自动实现service的切换 。
在针对rpg等长连接游戏类型时 , 玩家在场景中的移动都需要同步 , 广播给周围的玩家 , 但是rpc是单通道的 , 不能回传 , 这应该如何处理呢?
有借于此 , game-rpc增加了全双工的概念 , 不仅仅是client对service的请求 , 同时service也可以根据uniqueId , 进行主动推送 。 于是上面的流程图变成了下面这样:
RPC服务在游戏中的简单运用文章插图
一切看上去都很完美 , 似乎没有问题了 , 然而新的问题随之出现 。
我们知道 , 优秀的架构体系中 , 单点问题是不能容忍的 , 很不幸 , 我们的gateway , 就出现了单点 。 随着玩家数量的增加 , 整个服务都会处于不可用的状态 。 于是网关需要拆成集群的模式 , 新的架构图显示如下:
RPC服务在游戏中的简单运用文章插图
网关拆分后 , gate1和gate2的玩家是两个tcp长连状态的服务 , 无法交互 , 这应该怎么办?
我们参照了现行市面上比较常用的tcp网关做法 , 消息下行通知的解决方案 , 目前框架支持了两种方式:
  • MQ广播机制 , 当某台网关服务器收到广播消息后 , MQ通知给集群内的所有gate server , 每个gate在收到消息后 , 判断要推送端的消息是否是当前gate所持有的会话 , 如果在当前服务 , 则进行推送 , 否则抛弃

RPC服务在游戏中的简单运用文章插图