让我们假设我们有两个进程执行相同的代码,即两个进程都具有完全相同的代码库。该代码调用异步操作,该操作通过网络向第三进程发出请求。是否可以在进程#1上启动异步操作并在进程#2上继续处理?
public class ResourcesService : IResourcesService
{
public async Task<ResourcesData> GetResourcesData()
{
var cpuUsageData = await Services.GetService<ICpuService>().GetCpuUsageData();
var memoryData = await Services.GetService<IMemoryService>().GetMemoryData();
return new ResourcesData { CpuUsageData = cpuUsageData, MemoryData = memoryData };
}
}
基本上,通信是通过内部开发的消息传递来执行的,过程#1和过程#2都可以访问异步操作的结果。
问题是“是否可以在进程#1上发起对ICpuService.GetCpuUsageData的请求并在进程#2上继续执行?即是否有可能像异步/等待那样以某种方式破坏状态机的方法以便可以在不同的进程甚至在不同的服务器上恢复继续?”
答案 0 :(得分:1)
是的,有可能,但是除了工作负载分配问题(例如负载平衡,故障容忍等)之外,您还必须解决几个主要问题。首先,您可能需要使用Roslyn以类似于Roslyn does it的方式来自定义异步/等待状态机的生成,但需要进行必要的修改并将此自定义代码生成内置到通用的构建管道中。第二个问题与您需要在“分布式”状态机中引入的更改直接相关。特别是应该有序列化/反序列化机制,该机制将能够获取状态机实例的整个状态(包括自定义变量)并在线发送或从那里获取以恢复状态(状态应为所有状态同步)状态机的实例,以便继续操作可以使用相同的局部变量值)。显然,序列化和反序列化应该是代码生成的一部分,因为它必须处理局部变量。由于串行化通常具有一些限制(例如非公共成员序列化等),因此在这里可能会遇到一些陷阱,并且您不太可能只希望通过可序列化的类型来限制异步方法中局部变量的使用。最后,您需要在状态机内部生成分布式通信逻辑(可能在MoveNext
方法中)。但是又有一个陷阱:由于通信主要意味着I / O操作,因此您可能希望使用本机异步/等待机制来提高效率,这意味着在代码生成过程中应将分布式异步/等待机制与本机异步/等待机制区分开。 / p>
总结一下,我想说这是有可能实现的(需要大量的精力),但是由于异步/等待的设计重点是效率最高的I / O绑定操作,因此不太实用。但是,由于I / O操作的性质,分布式I / O负载(与分布式CPU负载不同)是非常奇怪的事情,其可伸缩性主要取决于通信通道带宽(网络,设备),而与计算单元(节点)的数量无关。 ,CPU,内核等)。
答案 1 :(得分:0)
对于此问题: “是否有可能像异步/等待一样以某种方式破坏状态机的方法,以便可以在不同的进程甚至在不同的服务器上恢复延续?”
您可能要使用Threading.Mutex。您可以命名互斥锁,以便可以与其他进程共享此互斥锁。该任务不适用于这种情况,但效果相似。 所以, App Instance1线程1-> MethodA(获取互斥锁)执行重要事项并释放Mutex App Instance1线程2-> MethodB正在等待Mutex发行,如果它是第一个获得发行的版本,它将获取Mutex并继续执行所需的操作 App Instance2线程-> MethodB正在等待Mutex发布,如果它是第一个获得发布的版本,它将获取Mutex并继续其需要做的事情
对于内部机器,事情变得复杂。