akka.net - 如何在 Akka.Net 中组合两个异步服务响应数据的响应
问题描述
我正在通过两个参与者进行两个异步服务调用
Actor 1 -> Fetch Data -> 这将返回一些响应
Actor 2 -> Fetch Data -> 这将返回一些响应。
如何在 Akka.Net 中结合这两个结果。在 Akka.net 中我们需要遵循什么模式吗?
解决方案
最简单的方法是使用询问模式:
ReceiveAsync<Message>(async msg => {
var t1 = actor1.Ask<Response>(new Request(), cancellationToken);
var t2 = actor2.Ask<Response>(new Request(), cancellationToken);
await Task.WhenAll(t1, t2);
DoSomething(t1.Result, t2.Result);
});
这种方法可以完成这项工作,但它几乎没有缺点:
- 它将阻止一个actor处理任何其他消息,直到整个方法完成执行(包括完成两个
t1
andt2
)。 - 它利用了
Ask
它有自己的性能影响 - 与例如相比并不大。数据库 I/O,但在许多情况下它可能太多(如果你担心性能)。
解决第 1 点的方法是从await
:
Receive<Message>(msg => {
var t1 = actor1.Ask<Response>(new Request(), cancellationToken);
var t2 = actor2.Ask<Response>(new Request(), cancellationToken);
Task.WhenAll(t1, t2).ContinueWith(t => {
var t1 = t.Result[0];
var t2 = t.Result[1];
return new CombinedResponse(t1.Result, t2.Result);
}).PipeTo(Self, sender: Sender);
});
Receive<CombinedResponse>(resp => DoSomething(resp.Result1, resp.Result2));
这将不需要参与者等待两个任务完成,同时可以自由处理其他消息。然而,这仍然使用任务和询问。
最后,可以只使用核心 akka 原语并简单地自己聚合部分响应。这通常可以使用所谓的聚合器模式来完成。有多种实现方式,但基本上它们都在相似的模型上运行:
- 继续计算需要多少参与者才能做出完整的响应。
- 将部分响应保存在缓冲区(列表)中,该缓冲区将填充来自其他参与者的传入响应。当演员响应时,减少等待的演员数量。一旦该数字达到 0,您就已经组装了一个完整的响应。
- 保留有关请求完整响应的原始参与者的信息
Sender
,以便在组装完整响应后向其发送结果(如有必要)。 Context.ReceiveTimeout
如果某些响应可能因任何原因无法到达,请使用防止无限等待。
推荐阅读
- java - 在 flatMap 的结果上使 Stream Parallel
- javascript - 如何使用 Javascript 覆盖 fetch?
- azure - Azure 容器实例托管(用户分配)身份无法获取 Keyvault 机密
- javascript - 试图在函数之外的JS中的数组中获取值并且该函数是异步的
- database - 可以在 Flutter Store BigData 中配置 Hive(一些 GB 文件)
- swift - 如何在反应本机应用程序的firebase auth文件夹中将UIWebView更改为WKWebview
- sql-server - 将 SQL Server 上的存储过程迁移到 HPL/SQL(Hadoop 生态系统)
- javascript - Vuejs 无法使用 axios 访问本地 json 文件。404(未找到)
- python - 如何获取类对象的数据,从他想要查看的对象的用户那里获取输入?
- r - 将 R 数据框转换为表格