• ET框架6.0分析三、网络通信


    概述

    ET框架的消息机制贯彻始终,包含Entity消息(Awake,Update ...),自定义(Customer)消息,网络消息等。而ET系统的进程包含了客户端、Gate等各种类型的服务器,进程包含各种服务器客户端之间通过网络消息进行通信进行工作。

    ET框架消息结构

    image

    • 结构图为了更加明确整体关系,进行了一定程度的简化,剔除掉了一些消息解包等一些细节

    • NetCompontent网络组件有Client客户端、Server服务器(Gate)、Inner内网服务等多态,进程业务使用网络组件进行通信,网络组件会对连接建立一个Secsiom会话对象,封装连接信息和相关操作

    • Service和Channel实现负责NetCompontent和Session的功能,有Tcp长连接、Web网页、KCP无连接可靠协议的多态(若不熟悉KCP协议,可以参考之前写的文章 跳转链接: KCP协议浅析)。

      • Channel对应一个Session连接,封装了对底层tcp等协议库的操作。
      • Service对应一个NetCompent组件,对应NetCompent管理多个Session,Server管理和调度一堆Channel的工作。
    • NetServices负责调度多个Service对象的在网络线程和主线程工作任务,ET开了网络线程处理网络相关,某些进程需要多个网络组件(比如Gate服务器同时需要Server、Inner网络组件,接收转发客户端消息)。

    • NetComponentOnReadEvent是不同类型网络组件的消息处理器。

      • NetClientComponentOnReadEvent对应客户端Client,处理普通消息和RPC调用。
      • NetInnerComponentOnReadEvent对应服务器内网类型Inner,处理Actor消息
      • NetServerComponentOnReadEvent对应服务外网,处理Actor消息、RPC调用、普通消息

    消息通信

    以典型的TCP协议类型为例,其他实现类似,看图相信都能理解,不多赘述。有一些要注意的点:

    • 如上述,ET开了一个线程处理网络相关,一些工作使用了“生产-消费”Task任务这种方式。
    • 使用了异步Socket

    TCP发消息

    image

    TCP收消息

    image

    多进程调用

    ET框架在基础网络消息通信基础使用了Actor模型、PRC等相关技术思想(某些思想和实现有调整)进行了拓展,提供多个进程的互相调用机制。
    先对相关技术做一个简介:

    • Actor模型

    在计算机科学中,Actor模型(Actor model)是一种并发运算上的模型。“Actor”是一种程序上的抽象概念,被视为并发运算的基本单元:当一个Actor接收到一则消息,它可以做出一些决策、创建更多的Actor、发送更多的消息、决定要如何回答接下来的消息。Actor可以修改它们自己的私有状态,但是只能通过消息间接的相互影响(避免了基于锁的同步)

    这是维基百科中对于Actor模型的描述,简单理解它就是提供了一种消息机制避免了基于锁的同步。一些经典的应用场景是多线程,在ET框架中它的应用场景是多进程,类似的它提供了一种机制:直接通过ID发消息,不用关心实例在哪个进程。

    • RPC

    分布式计算中,远程过程调用(英语:Remote Procedure Call,RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统

    RPC机制通过一些手段抹平了不同进程的差异,使得进程间的调用可以和本地异步调用一样处理。

    了解了这两种技术,下面来看ET框架对其的应用和如何实现多进程调用的。

    消息协议类型

    image
    如上图所示消息类型分为三种:

    • Message 消息,无需应答
    • Request 请求,对应一个Response应答
    • Response 应答,对应一个请求

    注意Request和Response一定成对定义,且其Message一定包含一个RpcId字段

    消息类型可以被前缀修饰,修饰有三种:

    • None 客户端与服务器(Gate)之间不需要转发的消息。(注意这里不是修饰字符不是"None",而是""表示没有)
    • Actor 服务器内网之间的消息
    • ActorLocation 客户端与服务器需要转发的消息。

    修饰字符可以修饰任意消息类型,组合起来一共有9种消息。
    如这个登录到Gate的协议:

    //ResponseType G2C_LoginGate
    message C2G_LoginGate // IRequest
    {
    	int32 RpcId = 1;
    	int64 Key = 2;  // 帐号
    	int64 GateId = 3;
    }
    
    message G2C_LoginGate // IResponse
    {
    	int32 RpcId = 1;
    	int32 Error = 2;
    	string Message = 3;
    	int64 PlayerId = 4;
    }
    
    • C2G_LoginGate 在消息名后面注明了消息类型,并在消息名上面注明了应答包的消息类型,并且包含一个RpcId的字段,这些都必须的,表示这是个不需要转发的、需要应答的请求消息。而消息名前缀只是方便理解,起到注释的作用:表示这是Client进程发送给Gate服务器进程的消息。
    • G2C_LoginGate 同上,是上述C2G_LoginGate请求的应答消息。

    Rpc调用过程

    image
    如图所示,进行Rpc调用时,生成一个新的RpcID并带入请求包中,同时把调用信息存起来。对方应答时,会把请求包的RpcID传入到应答包中。在收到消息时如果是Resp类型消息会调用OnResp方法,通过应答包的RpcID取出RpcInfo,通过RpcInfo取消调用RpcCall函数的异步阻塞。

    public static void OnResponse(this Session self, IResponse response)
    {
    	if (!self.requestCallbacks.TryGetValue(response.RpcId, out var action))
    	{
    		return;
    	}
    
    	self.requestCallbacks.Remove(response.RpcId);
    	if (ErrorCore.IsRpcNeedThrowException(response.Error))
    	{
    		action.Tcs.SetException(new Exception($"Rpc error, request: {action.Request} response: {response}"));
    		return;
    	}
    	action.Tcs.SetResult(response);
    }
    

    action.Tcs.SetResult会取消异步的阻塞,执行await后面的语句,详情见之前写的文章 跳转链接: C#异步编程

    Actor模型实现

    在ET框架的设计中,Actor其实是一个带有MailboxComponent的组件。其具体的实现方式,ET有比较详细的文档说明,有实现思路和使用方式的介绍,这里贴出来,不做赘述。
    跳转链接: ET Actor模型 官方介绍

    参考链接

  • 相关阅读:
    关于在 Notion 中使用 Markdown 语法
    点云从入门到精通技术详解100篇-基于激光点云的道路目标检测(续)
    【C++】map与set的封装
    经营管理智能化,中小型商贸线上融合
    国庆作业day3
    2022 SWPU新生赛&HNCTF web部分题目
    Springcloud之OAuth2
    UI组件DevExpress ASP.NET Core v22.1亮点 - 甘特图、UI组件全新升级
    java版网页代码生成器系统myeclipse定制开发mysql数据库网页模式java编程jdbc生成无框架java web网页
    神经系统的结构是什么,什么是链状神经系统
  • 原文地址:https://www.cnblogs.com/hggzhang/p/17214635.html