ToB企服应用市场:ToB评测及商务社交产业平台
标题:
.NET分布式Orleans - 2 - Grain的通信原理与界说
[打印本页]
作者:
美丽的神话
时间:
2024-5-15 04:51
标题:
.NET分布式Orleans - 2 - Grain的通信原理与界说
Grain 是 Orleans 框架中的基本单元,代表了应用程序中的一个实体或者一个计算单元。
每个Silo都是一个独立的进程,Silo负责加载、管理和实行Grain实例,并处理来自客户端的请求以及与其他Silo之间的通信。
通信原理
在相同的Silo中,Grain与Grain之间的通信通过直接的方法调用实现。每个Silo都维护了一个Grain的运行时环境,当一个Grain需要调用另一个Grain时,它可以直接调用目标Grain的方法,无需经过网络传输,示意图如下所示:
在差别的Silo中,Grain与Grain之间的通信需要通过消息传递的方式实现。当一个Grain需要与另一个Silo中的Grain通信时,它会将消息发送给目标Grain所在的Silo,目标Silo接收到消息后,将其路由到目标Grain,然后目标Grain处理消息并返回效果。示意图如下所示:
外部客户端与Silo之间的通信是通过网络消息传输实现的。客户端需要利用Orleans提供的客户端库与Silo创建连接,并发送请求消息到目标Silo,目标Silo接收到消息后,举行处理并返回效果。在Orleans中,客户端与Silo之间的通信利用了一种名为Orleans Messaging Protocol (OMP)的自界说协议,用于保证通信的可靠性和服从。示意图如下所示:
内置端口
默认情况下,Orleans 将侦听端口 11111 用于silo之间通信,在端口 30000 上举行客户端到接收器通信。可以通过以下方式设置这些端口
siloBuilder.Configure<EndpointOptions>(options =>
{
// Port to use for silo-to-silo
options.SiloPort = 11_111;
// Port to use for the gateway
options.GatewayPort = 30_000;
// IP Address to advertise in the cluster
options.AdvertisedIPAddress = IPAddress.Parse("172.16.0.42");
// The socket used for client-to-silo will bind to this endpoint
options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40_000);
// The socket used by the gateway will bind to this endpoint
options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50_000);
})
复制代码
在内部,silo 将侦听 0.0.0.0:40000 和 0.0.0.0:50000,但在长期化提供程序中发布的值将是 172.16.0.42:11111 和 172.16.0.42:30000
GrainKey类型
在 Orleans 中,可以利用差别类型的键来标识 Grain。下面是几种常用的 GrainKey 接口:
IGrainWithStringKey: 利用字符串作为键的接口。适用于需要以字符串情势标识的场景,比如用户名称、订单号等。
IGrainWithGuidKey: 利用 Guid 作为键的接口。适用于需要全局唯一标识的场景,比如唯一的实体对象、全局唯一的标识符等。
IGrainWithIntegerKey: 利用整数作为键的接口。适用于需要连续递增或递减的序列标识的场景,比如自增主键、序列号等。
IGrainWithGuidCompoundKey: 利用复合的 Guid 作为键的接口。
IGrainWithIntegerCompoundKey: 利用复合的整数作为键的接口。
IGrainWithGuidCompoundKey: 利用复合的字符串作为键的接口。
下面是利用 IGrainWithStringKey 界说的 IPlayerGrain 接口,并为其增加了买装备的动作,并将买完的装备生存至内存中:
public interface IPlayerGrain : IGrainWithStringKey
{
Task BuyEquipment(string equipmentName);
Task<List<string>> GetOwnedEquipments();
}
public class PlayerGrain : Grain, IPlayerGrain
{
private IPersistentState<List<string>> _ownedEquipments;
public PlayerGrain([PersistentState("ownedEquipments", "playerGrainStorage")] IPersistentState<List<string>> ownedEquipments)
{
_ownedEquipments = ownedEquipments;
}
public async override Task OnActivateAsync(CancellationToken cancellationToken)
{
await base.OnActivateAsync(cancellationToken);
// 在激活时从持久化状态中加载数据
await _ownedEquipments.ReadStateAsync();
if (_ownedEquipments.State == null)
{
_ownedEquipments.State = new List<string>();
await _ownedEquipments.WriteStateAsync(); // 将空列表持久化到存储中
}
}
public async Task BuyEquipment(string equipmentName)
{
_ownedEquipments.State.Add(equipmentName);
await _ownedEquipments.WriteStateAsync(); // 将更新后的装备列表持久化到存储中
}
public Task<List<string>> GetOwnedEquipments()
{
return Task.FromResult(_ownedEquipments.State);
}
}
复制代码
调用时利用IGrainFactory.GetGrain方法即可
var host = Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
services.AddOrleans(builder =>
{
builder
.UseLocalhostClustering()
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "dev";
options.ServiceId = "OrleansExample";
})
.AddMemoryGrainStorage("playerGrainStorage");
});
})
.ConfigureLogging(l => l.AddConsole())
.Build();
await host.StartAsync();
var client = host.Services.GetRequiredService<IGrainFactory>();
var palyer = client.GetGrain<IPlayerGrain>(Guid.NewGuid().ToString());
await palyer.BuyEquipment("Sword");
(await palyer.GetOwnedEquipments()).ForEach(Console.WriteLine);
复制代码
IGrainFactory 和 IClusterClient
在 Orleans 中,IGrainFactory 和 IClusterClient 都是用于创建和获取 Grains 的接口,但它们的作用和利用场景略有差别。
IGrainFactory:
IGrainFactory 是 Orleans 用于集群中创建 Grains 的工厂接口。 它通常用于在 Orleans Silo 或者 Orleans Client 中创建 Grains 实例。
在 Silo 中,您可以通过依靠注入或者直接实例化一个 IGrainFactory 对象来创建 Grains。
在 Silo 外部,比如 Orleans Client 中,您也可以通过依靠注入或者直接实例化一个 IGrainFactory 对象来创建 Grains。
// 通过依赖注入或直接实例化一个 IGrainFactory 对象
IGrainFactory grainFactory = serviceProvider.GetRequiredService<IGrainFactory>();
var grain = grainFactory.GetGrain<IMyGrain>(grainId);
复制代码
IClusterClient:
IClusterClient 是 Orleans 中用于与 Orleans 集群举行通信的客户端接口。 它通常在 Orleans Client 中利用,用于与 Orleans Silo 举行通信,以调用 Grains 的方法或者获取 Grains 的引用。
IClusterClient 是 IGrainFactory 的一个超集,除了可以创建 Grains,还可以实行其他集群相关的操作,比如管理 Silo 的生命周期、订阅集群中的事件等。
// 通过依赖注入或直接实例化一个 IClusterClient 对象
IClusterClient clusterClient = serviceProvider.GetRequiredService<IClusterClient>();
var grain = clusterClient.GetGrain<IMyGrain>(grainId);
复制代码
总的来说,IGrainFactory 主要用于在应用程序内部直接创建 Grains,而 IClusterClient 则更适合用于外部Client与 Orleans 集群举行通信,包括创建 Grains 和实行其他集群操作。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4