实现一个轻量的分布式服务器可靠通信组件#1

最近实现了一个分布式游戏服务器间进行远程通信的组件
整体的感觉是在应用层又自己简单实现了一遍IP层+TCP层做的事w(゚Д゚)w

实现一个轻量的分布式服务器可靠通信组件#1_第1张图片
分布式服务器结构

对于服务器间通信,现有的做法是:
1.直连的服务器间
通过封装的SendMsg接口实现点对点或广播

2.非直连的服务器间
人工规划传输过程
这个过程如果以传纸条作比方的话,就是:
小红如果想给小明传纸条,需要把纸条给小刚,并且告诉小刚再把纸条给小兰,并且告诉小兰把纸条交给小明。最后由小兰把纸条交到小明手上。
如果小红事先不认识小刚,或者小红不知道小刚认识小兰,或者小红不知道小兰认识小明,这纸条就传不了。


实现一个轻量的分布式服务器可靠通信组件#1_第2张图片
非直连服务器消息传输

可以看到对于非直连的服务器目前的通信方式存在几个问题
1.传输过程依赖使用者提前规划
2.发送方无法判断接收方实际的连接状态,哪怕是没有连接到网络中的目标也会选择发送

设计方向

1.利用现有的网络结构实现服务器间的消息转发,不添加额外的网络连接
2.每个进程(节点)可以感知到整个网络中的所有节点,并与其通信
3.支持通过节点id发送消息(点对点)和通过节点类型发送消息(广播)
4.发送者只需声明目标节点id或类型,无需关心传输过程,路径规划以及消息转发由模块内部完成
设计的重点和难点
1.网络拓扑结构管理

a.将通过网络互连的服务器进程组抽象为一张有向图。服务器进程对应图中的节点,网络连接对应有向边(由sock客户端指向sock服务器)
b.每个节点根据网络连接的连接或者断开,维护本地记录的网络拓扑结构,并同步给相邻的节点
c.根据其他节点同步过来的信息更新网络拓扑结构

2.发包管理

a.可以直接向指定目标节点发包,也可以根据节点类型筛选出一批节点进行广播
b.根据本地维护的拓扑结构规划传输路径,向路径中的下一跳节点发送消息包
c.接收远程数据包,选择转发或者本进程处理

3.可靠传输控制

对于没有直接网络连接关系的一对节点,消息包会经过若干个中间节点的转发后到达目标节点
这就不能再依赖原有的传输层协议(TCP)来保证一对通信节点间消息收发的可靠性和有序行,需要由模块通过自己的机制来实现

可靠性
A节点发往B节点的包需要保证B节点一定能够收到
如果由于中间节点宕机或者其他问题导致丢包,需要由模块重发,直到B收到为止

有序性
由于网络结构是图结构,一对节点间的通路可能有多条,这会导致连续发送的包不保证以同样的过程传过中间的网络。
A先后发给B节点packet1和packet2两个包,对B的上层应用来说要先感知packet1再感知packet2
如果实际上B先收到了packet2,需要等待packet1到达之后再转交给上层处理

事实上可选择的分布式网络通信模式不止一种,在讨论初期有几种其他的可选方向

1.消息队列(MessageQueue,如Rabbit、Active、Kafka等)

优点:
有成熟的企业级框架可以直接使用
缺点:
消息队列的实时性并不强
对于游戏服务器的通信显得过重,实际只需要一个轻量级的通信组件

2.中心通信节点(组)

增加一个专门用于消息转发的中心节点,所有服务器进程都与其建立连接,消息的发送全部通过中心节点转发
优点:
理解起来简单
消息传输路径明确
缺点:
对中心节点的稳定性要求非常高,节点挂掉之后整个网络内部的通信将瘫痪
当服务器进程不断增多时,中心节点可能成为瓶颈,单个节点可能不满足需求,需要以进程组的方式存在
如果以进程组的方式实现,则需要处理动态扩容以及负载均衡等问题

经过讨论最后还是决定先实现一版基于图结构的分布式通信方法

具体的实现细节请参见后续篇幅:
网络拓扑结构管理
发包管理
可靠传输控制
其他待补充

你可能感兴趣的:(实现一个轻量的分布式服务器可靠通信组件#1)