我在ASP.NET中使用RESTful API创建了一个服务,该服务托管在IIS中.在这个服务中,我想用Akka.NET创建一个actor系统.
在创建actor系统时:
var actorSystem = ActorSystem.Create("myActorSystem");
Run Code Online (Sandbox Code Playgroud)
抛出以下异常:
System.Web.dll中发生类型为"System.InvalidOperationException"的第一次机会异常附加信息:此时无法启动异步操作.异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动.如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async ="true"%>.此异常还可能表示尝试调用"异步void"方法,该方法通常在ASP.NET请求处理中不受支持.相反,异步方法应该返回一个Task,调用者应该等待它.
actor系统本质上是一个并发系统,在actor之间交换异步消息.正如这里所解释的那样,这个actor系统无法在IIS中取消AppDomain,这可能就是为什么抛出上述异常的原因.
本文介绍如何在ASP.NET中运行后台任务.但是,我不知道如何将它用于我的actor系统,因为我无法控制可能由Akka.NET创建的后台任务的生命周期.
有没有办法使这项工作,或者我应该放弃在ASP.NET应用程序中使用actor系统的想法?
编辑:我还在Stackoverflow上看到一个关于使用Akka实现REST服务的问题.关于类似于Spray工具包的解决方案的任何建议,但欢迎为Akka.NET工作.
我已经使用NGEN来创建我的应用程序使用的几个程序集的本机映像.但是,运行应用程序时不会加载这些图像,我不知道为什么.
这是来自fuslogvw的典型日志:
*** Assembly Binder Log Entry (2/05/2012 @ 13:29:04) ***
The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\MyDir\MyApp.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = ***\***
LOG: DisplayName = MyAssembly, Version=1000.0.0.0, Culture=neutral, PublicKeyToken=null (Fully-specified)
LOG: Appbase = file:///C:/MyDir/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = …Run Code Online (Sandbox Code Playgroud) 我正在使用 Akka.NET 来实现一个角色系统,其中一些角色是按需创建的,并在可配置的空闲期后被删除(为此我使用了 Akka 的“ReceiveTimeout”机制)。这些actor中的每一个都由一个key来标识,并且不应该存在两个具有相同key的actor。
这些演员目前由一个共同的监督者创建和删除。可以要求监督者返回对与给定键匹配的演员的引用,通过返回现有的或创建新的(如果具有此键的演员尚不存在)。当演员收到“ReceiveTimeout”消息时,它会通知主管,主管又会用“PoisonPill”杀死它。
在删除消息后立即向其中一个演员发送消息时,我遇到了问题。我注意到向死者发送消息不会产生异常。更糟糕的是,当发送“Ask”消息时,发送者仍然处于阻塞状态,无限期地(或直到超时)等待他永远不会收到的响应。
我首先想到了 Akka 的“Deatchwatch”机制来监控演员的生命周期。但是,如果我没记错的话,垂死的actor发送的“Terminated”消息会像任何其他消息一样被监控actor异步接收,所以问题可能仍然出现在目标actor的死亡和它的接收之间“已终止”消息。
为了解决这个问题,我这样做是为了让任何要求主管提供对此类演员的引用的人都必须向主管发送“关闭会话”消息以在他不再需要演员时释放他(这是透明地完成的)通过一次性“ActorSession”对象)。只要演员上有任何打开的会话,主管就不会删除它。
我想这种情况很常见,因此我想知道是否没有更简单的模式来解决此类问题。任何建议将不胜感激。
我们有一个微服务架构并应用CQRS模式.发送到微服务的命令触发应用程序状态更改以及在Kafka总线上发出相应事件.我们将这些事件投射到使用ElasticSearch构建的读取模型中.
到现在为止还挺好.
我们的微服务最终相互一致.但在任何时候,它们都不是(必然).因此,他们发送的事件也不总是彼此一致.
此外,为了保证应用程序状态更改与相应事件的发布之间的一致性,我们在同一事务中保持DB新状态和相应事件(我知道我们可以使用事件源并避免完全持久化状态).然后,异步工作人员负责在Kafka总线上发送这些事件.此模式保证每个状态更改至少发送一个事件(这不是问题,因为我们的事件是幂等的).但是,由于每个微服务都有自己的事件表和异步工作程序,因此我们无法保证事件将按照各自微服务中发生相应状态更改的顺序发送.
编辑:澄清一下,每个微服务都有自己的数据库,自己的事件表和自己的工作者.特定工作程序按照它们在相应事件表中持久化的顺序处理事件,但不同事件表上的不同工作程序(即不同的微服务)不提供此类保证.
在同一ElasticSearch文档中从不同的微服务中投射这些不连贯或无序事件时会出现问题.
一个具体的例子:让我们想象一下由不同的微服务管理的三种不同的聚合A,B和C(在域驱动设计意义上的聚合):
其中一个用例是通过ElasticSearch查找绑定到聚合B的所有聚合A,聚合B又绑定到具有特定名称的聚合C.
如上所述,单独的事件表和工作人员可能在来自不同微服务的事件发射之间引入可变延迟.创建A,B和C并将它们绑定在一起可能会导致以下事件序列:
一批事件的另一个例子:假设我们最初有聚合B和C,并且同时发出两个命令:
这可能导致事件:
具体而言,我们无法在ElasticSearch文档中投影这些事件,因为事件有时会引用不再存在或尚不存在的聚合.任何帮助,将不胜感激.
domain-driven-design cqrs elasticsearch apache-kafka microservices
假设我们有以下内容:
DDD聚合了A和B,A可以引用B。
管理 A 的微服务公开以下命令:
管理 B 的微服务公开以下命令:
成功的创建、删除、链接或取消链接总是会导致执行该操作的微服务发出相应的事件。
为这两个微服务设计事件驱动架构的最佳方法是什么,以便:
具体来说,以下示例可能会导致暂时的不一致状态,但最终必须在所有情况下恢复一致性:
示例 1
示例 2
示例 3
我有两个解决方案。
解决方案1