- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
ET框架的消息机制贯彻始终,包含Entity消息(Awake,Update ...),自定义(Customer)消息,网络消息等。而ET系统的进程包含了客户端、Gate等各种类型的服务器,进程包含各种服务器客户端之间通过网络消息进行通信进行工作.
结构图为了更加明确整体关系,进行了一定程度的简化,剔除掉了一些消息解包等一些细节 。
NetCompontent网络组件有Client客户端、Server服务器(Gate)、Inner内网服务等多态,进程业务使用网络组件进行通信,网络组件会对连接建立一个Secsiom会话对象,封装连接信息和相关操作 。
Service和Channel实现负责NetCompontent和Session的功能,有Tcp长连接、Web网页、KCP无连接可靠协议的多态(若不熟悉KCP协议,可以参考之前写的文章 跳转链接: KCP协议浅析 ).
NetServices负责调度多个Service对象的在网络线程和主线程工作任务,ET开了网络线程处理网络相关,某些进程需要多个网络组件(比如Gate服务器同时需要Server、Inner网络组件,接收转发客户端消息).
NetComponentOnReadEvent是不同类型网络组件的消息处理器.
以典型的TCP协议类型为例,其他实现类似,看图相信都能理解,不多赘述。有一些要注意的点:
ET框架在基础网络消息通信基础使用了Actor模型、PRC等相关技术思想(某些思想和实现有调整)进行了拓展,提供多个进程的互相调用机制。 先对相关技术做一个简介:
在计算机科学中,Actor模型(Actor model)是一种并发运算上的模型。“Actor”是一种程序上的抽象概念,被视为并发运算的基本单元:当一个Actor接收到一则消息,它可以做出一些决策、创建更多的Actor、发送更多的消息、决定要如何回答接下来的消息。Actor可以修改它们自己的私有状态,但是只能通过消息间接的相互影响(避免了基于锁的同步) 。
这是维基百科中对于Actor模型的描述,简单理解它就是提供了一种消息机制避免了基于锁的同步。一些经典的应用场景是多线程,在ET框架中它的应用场景是多进程,类似的它提供了一种机制:直接通过ID发消息,不用关心实例在哪个进程.
分布式计算中,远程过程调用(英语:Remote Procedure Call,RPC)是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一个地址空间(通常为一个开放网络的一台计算机)的子程序,而程序员就像调用本地程序一样,无需额外地为这个交互作用编程(无需关注细节)。RPC是一种服务器-客户端(Client/Server)模式,经典实现是一个通过发送请求-接受回应进行信息交互的系统 。
RPC机制通过一些手段抹平了不同进程的差异,使得进程间的调用可以和本地异步调用一样处理.
了解了这两种技术,下面来看ET框架对其的应用和如何实现多进程调用的.
如上图所示消息类型分为三种:
注意Request和Response一定成对定义,且其Message一定包含一个RpcId字段 。
消息类型可以被前缀修饰,修饰有三种:
修饰字符可以修饰任意消息类型,组合起来一共有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;
}
如图所示,进行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#异步编程 。
在ET框架的设计中,Actor其实是一个带有MailboxComponent的组件。其具体的实现方式,ET有比较详细的文档说明,有实现思路和使用方式的介绍,这里贴出来,不做赘述。 跳转链接: ET Actor模型 官方介绍 。
最后此篇关于ET框架6.0分析三、网络通信的文章就讲到这里了,如果你想了解更多关于ET框架6.0分析三、网络通信的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我一直在学习如何使用 ets,但困扰我的一件事是,偶尔*,ets:match 会抛出一个错误的参数...而且,从他们开始,所有后续调用(甚至之前有效的调用)也会抛出一个错误参数: > ets:matc
我正在尝试使用指数平滑方法创建预测,但得到错误“非季节性数据”。这显然不是真的 - 请参阅下面的代码。 为什么我收到这个错误?我应该使用不同的函数(它应该能够执行简单的、双重的、阻尼趋势的、季节性的、
I'm writing a program using Elixir and I have a very strange error.我正在用长生不老药编写程序,我有一个非常奇怪的错误。 I
I'm writing a program using Elixir and I have a very strange error.我正在用长生不老药编写程序,我有一个非常奇怪的错误。 I
我在 erlang 中使用 ets:select 有一个奇怪的行为。 我获得了正确的 select 语句(下面的 4 和 5),然后在我的语句中出错(下面的 6),然后我再次尝试与 4 和 5 中相同
如果我想将 ETS 表用于共享状态,是否有任何已建立的机制来等待插入 ETS 表? 我知道 mnesia 支持表事件,我在想一个类似的机制对普通 ETS 很有用,这样一个进程就可以等待它需要的数据被加
ets 包的delete_object 的运行时间是多少?鉴于有 n 个条目具有相同的键 k,delete_object 的运行时间是否为 O(n)或者O(1)?如果确实是 O(1),lookup 操
我们想知道如何有效地查找两个 ets 表之间的相互元素,我们尝试了 ETS 和 QLC 模块,但不知道如何做到这一点,我们在 [bag] 选项上使用 ets,这意味着同一个键有多个值。 我们正在寻找最
ETS set 是否保证元组的内部顺序与其插入顺序相同?例如:我通过每秒插入一个元组来保留日志,时间戳是关键。在此示例中,set 是否保证元组按键排序? 我知道ordered_set会做我希望的事情,
具体来说,:ets.tab2list 和 :ets.file2tab。这些函数是否“快照”表状态,或者其他操作是否可以在这些函数完成时交错读取和写入? 最佳答案 基于文档 here : Functio
我是 Erlang 新手。我有一个关于 ets 表的问题。 我有两个 ets 表,我需要从两个表中插入或删除值。 insert(V) -> ets:insert(table_test,V),
我使用 elang ets 表作为一个简单的缓存。我想使用一个进程来扫描表并删除过期元素(多个)。 使用 ets:foldl expire_table_example() -> Tab = ets:n
我在使用 ets:match 时遇到问题。在下面的代码中,我希望 ets:match 返回 1 个找到的值,但没有返回任何值。为什么? 1> T = ets:new(xxx, []). 16400 2
我在一个进程中创建了 ETS 表,我想在另一个进程中使用它。我如何在第二个过程中“打开”ETS 表?在手册页中找不到好的功能。 最佳答案 您必须使用“named_table”和“public”选项创建
我通过 elixir 使用 ets 作为一个简单的内存持久层来存储和检索键,以及偶尔的 foldl,这涉及减少许多具有不同值的重复键。我正在使用包选项。 是否有一种简单的,也许是 O(1) 的方法来检
我正在考虑在一个新的 Elixir 项目中使用 Erlang 的 ETS 作为用户搜索的缓存。根据用户输入,系统将使用昂贵的第三方 API 进行查找。 为了避免对相同的用户输入进行重复调用,我打算在外
在调试使用信号量进行跨进程同步的应用程序时,我偶然发现了使用PowerShell代替“其他”进程的想法。在PowerShell中执行以下操作可以正常工作: // In C# application:
我对从 ets 表中选择的性能进行了一些测试,并注意到了奇怪的行为。例如,我们有一个简单的 ets 表(没有任何特定选项),它存储键/值 - 一个随机字符串和一个数字: :ets.new(:table
我有一些这样的代码: Table = ets:new(table, [bag]), true = ets:insert(Table, {bucket_1, some_value_1}), true =
假设我有一个 ets 表,例如: I = ets:new(mytable, [named_table, set]). ets:insert(I, {10,{10, 4 ,"description"})
我是一名优秀的程序员,十分优秀!