美文网首页
实现一个轻量的分布式服务器可靠通信组件#2

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

作者: 李相赫的乐芙兰 | 来源:发表于2019-11-16 20:48 被阅读0次

    网络拓扑结构是保证整个模块能够正确运作的基础。如果本地进程无法感知远程进程,或者结构信息是错误的,则其他所有的事情都无从谈起。
    实现的难点在于两个部分
    1.分布式图结构缺少仲裁节点(中心),需要一套机制来保证不同节点的唯一性,并被远程节点接受
    2.网络结构是动态的,连接的建立与断开会随时发生,并且任意的节点、连接都有可能发生变化,而这些变化需要同步给整个网络中的所有节点

    设计初期有想过将图结构通过某种规则进行删边从而转换为一颗树,以树根作为仲裁节点
    不过这样做有两个主要问题:
    1.规则的制定依赖于每个具体项目的需求,很难做到统一
    2.对于某些特殊的断线情况,树形结构不能完全支持目前的网络传输逻辑
    所以最终还是坚持以图结构来维护动态的网络拓扑结构

    对于进程的抽象(节点):

    需要满足这几个需求:

    1.通过全局唯一的oid来标识一个进程,并且同一个进程无论重启多少次都需要保证oid一致

    解释一下为什么要保证重启之后的一致性:
    以一个跨服分组下的两个游戏服A和B为例,对A来说B只有逻辑上的意义,并且认为只存在一个B,与它是否重启过,重启了多少次都没有关系。
    如果B的oid变了,A只会认为是网络中新加入了另外一个游戏服C

    2.带有服务器类型标记,可以通过类型筛选出所有满足需要的节点
    3.记录所有网络连接信息(有向边),为消息同步和路径规划提供基础
    对于连接的抽象(有向边):

    需要满足这几个需求:

    1.通过边的有无(或者边的状态)来反映实际的网络连接状态
    2.远程节点根据同步消息中的边信息,可以更新它所维护的网络拓扑结构

    由于同步消息也是依靠分布式网络传输的,同样无法保证有序性,即旧的结构信息可能比新的结构信息晚到达。
    这就要求给边加上版本号:收到同步消息时,根据版本号大小来判断是否需要更新对应的边,若当前消息中的版本号比本地存的要小,则不更新对应的边。
    实际上也不能单纯的根据版本号大小来判断:
    版本号大的就一定是更新的边信息么?这还得看版本号的生成机制。假如是通过进程启动时从1开始计数这类的方式,由于进程重启后边的版本号会重置,对进程直接相连的边来说它的版本号是很小的,但不能被后续到来的同步消息中远程节点存储的“旧版本”的边所替代。
    我处理的方法是:

    a.每次收到同步包,先按包内的信息更新一遍
    b.然后对于本节点的直连边,检查边的实际连接状态,若与信息不一致,则以实际状态为准再更新一次
    c.并且令边的版本号+1,再向外广播一次结构更新
    
    ///进程节点
    struct GraphNode
    {
        UINT64 m_oid;           ///唯一oid
        ESvrNodeType m_nodeType;///节点类型
        vector<UINT> m_outEdges;///所有出边
        vector<UINT> m_inEdges; ///所有入边
    }
    
    ///有向边
    struct GraphEdge
    {
        bool m_isInUse;     ///是否有效
        UINT m_id;          ///本地编号
        UINT64 m_from;      ///边起始节点
        UINT64 m_to;        ///边指向节点
        UINT64 m_version;   ///版本号
    }
    

    关于图节点唯一oid的生成方式,目前是通过:服务器类型+组ID+配置文件ID的方式组合而成

    图结构更新、维护的完整逻辑:
    (这里的客户端、服务器是相对socket连接来说的,并不是指客户端程序和服务器程序)

    1.客户端进程监听到连接建立事件后,向服务器进程发送握手消息,消息中包括:自身节点oid + 本地维护的图结构信息
    2.服务器进程收到握手消息后,根据客户端的图结构信息更新自身的图结构信息(通过边的版本号),更新完成后将本地的图结构信息推送给所有相邻节点(包括这个客户端进程对应的节点)
    3.相邻进程收到更新消息后,通过消息内的信息更新本地图结构。若发现本地信息需要修改,则将修改后的完整信息再次推送给所有相邻节点;若本地信息已经是最新,则终止信息的传递
    连接断开时的逻辑类似,只不过不再需要客户端先发握手消息,直接由断开连接的双方各自处理即可
    
    拓扑结构管理

    相关文章

      网友评论

          本文标题:实现一个轻量的分布式服务器可靠通信组件#2

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