3

聊聊GS引入MQ的一些实践

 3 years ago
source link: https://wudaijun.com/2021/02/gs-mq-practice/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

聊聊GS引入MQ的一些实践

发表于

2021-02-18 分类于 gameserver

阅读次数: 2 Valine: 0

在目前这套项目架构诞生初期,基于当时的游戏类型和项目需求,架构做得相对简单,设计上尽可能通过goroutine而不是节点来并发,节点间用ETCD做服务发现,用gRPC做节点通信,在单向依赖,弱藕合的情况下,基本能够满足需求。对于个别强耦合的节点交互,使用gRPC Stream来建立双工连接。

随着游戏类型和业务需求的变更,跨服功能增多,节点划分越来越细,藕合越来越重,网络拓扑也越来越复杂。gRPC Stream不再能很好地胜任。

因此我们考虑用一套新的节点交互方案,大概有两个思路:

  1. 写一套完备的TCP网络库(包含服务发现,自动重连,编解码,心跳,流控等),用于统一节点间甚至Gateway与Client间的网络交互
  2. 使用MQ解耦集群内节点交互,将网状网络化为星形网络,简化网络拓扑

在对方案一进行几天的尝试后,我们最终放弃了TCP方案,主要有以下几个问题:

  1. 网络拓扑完全交给了应用层去维护,开发者需要谨慎规划和约束,避免形成全联通
  2. 由于不是全联通网络,A->B的消息可能需要经由一个甚至多个中间节点路由才能到达,并且这类路由信息只能逻辑层维护
  3. 某些业务场景下,节点路由和依赖可能是动态的,如跨服匹配战场,此时需要动态建立/销毁连接以维护动态路由

就前面几个问题来说,MQ是更好的解决方案,相比TCP,它有以下优势:

  1. 将 0-N 跳的路由网络的模型,统一为一跳,即通过中间件即可直达任意节点,在路由和全联通之间找到一个平衡点
  2. 发布订阅模型,为应用层提供了非常大的灵活度: 单向依赖/双向依赖,扇入/扇出,负载均衡,批量发布(主题匹配)等

消息中间件能够比较好地向应用层屏蔽节点路由的问题,但它并不能完全替代ETCD+gRPC,两套方案可以在不同的应用场景搭配使用。

在对几种主流消息中间件进行评估之后,我们目前选定nats,它的优点是基于golang编写,轻量级,高性能,低延迟,缺点是不支持消息持久化,即最多一次投递语义,nats-streaming基于nats增加了消息持久化,即最少一次投递语义,相应的也有更完备的流控机制。由于游戏服务器对消息时延敏感,并且大部分消息有状态和时效性,因此目前打算直接用nats,关键逻辑自己做消息QoS或容错机制(官方也推荐nats,由应用层而不是中间件去做QoS)。

从设计上而言,在nats之上封装应用层MQ API,不依赖nats特有功能(如Request-Reply),只使用消息中间件的通用语义(Publish/Subscribe),解耦组件以实现必要时透明替换,应用层对MQ API的使用主要分两种:

  1. 节点通信: 应用在藕合较强的逻辑节点间,在这里Topic类似于节点公开通信地址,MQ起到的作用类似TCP。这情况情形下,对MQ封装通用消息语义: Send / Request / Async-Request,前两种语义容易理解,即异步投递和同步请求,第三种是异步请求,通过回调的方式处理响应,并统一保存请求上下文,适用于异步RPC情景。更进一步,这一层消息语义封装不应该依赖于MQ封装,即可以透明将这层语义的底层实现由MQ换成TCP或其它传输层,同时应该向应用层屏蔽掉Topic,提供类似EndPoint或Peer的抽象概念。
  2. 发布订阅: 消息中间件的常规应用,但是也需要封装,一方面是为了解耦屏蔽nats,另一方面是构建应用层对订阅分发的优化,就我们目前的实践而言,建立了一个固定大小的mq worker pool,以Topic Hash为请求分配worker,每个worker内部做二级分发(优化同一个节点对同一个Topic的多次订阅),序列化/反序列化等,worker底层复用同一个nats client,对逻辑层提供足够易用的异步发布订阅接口。

关于MQ的进一步实践我们还在摸索,目前的体会是,消息中间件和网关一样,都是游戏服务器架构的基础设施,前者对内简化服务器节点网络拓扑,后者对外屏蔽服务器内部网络拓扑,共同提升服务器的可扩展性。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK