我在ASP.NET中使用RESTful API创建了一个服务,该服务托管在IIS中。在这个服务中,我想用Akka.NET创建一个actor系统。
创建演员系统后:
var actorSystem = ActorSystem.Create("myActorSystem");
抛出以下异常:
类型' System.InvalidOperationException'的第一次机会异常。发生在System.Web.dll中 附加信息:此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async =" true" %取代。此异常也可能表示尝试调用" async void"方法,在ASP.NET请求处理中通常不受支持。相反,异步方法应该返回一个Task,调用者应该等待它。
actor系统本质上是一个并发系统,在actor之间交换异步消息。正如here所解释的那样,这个actor系统无法在IIS中取消AppDomain,这可能就是为什么抛出上述异常的原因。
This article解释了如何在ASP.NET中运行后台任务。但是,我不知道如何将它用于我的actor系统,因为我无法控制可能由Akka.NET创建的后台任务的生命周期。
有没有办法让这项工作成功,还是应该放弃在ASP.NET应用程序中使用actor系统的想法?
编辑:我还在Stackoverflow上看到了一个关于implementing a REST service using Akka的问题。关于类似于Spray toolkit的解决方案的任何建议,但欢迎为Akka.NET工作。
答案 0 :(得分:25)
我已经在ASP.NET MVC应用程序中使用了Akka.NET和Akka.Remote,这些应用程序在EC2上每秒最多执行1000个请求 - 所以我将分享我曾经使用的一些提示和技巧启动并成功运行。有一个原型版本甚至使用Akka.Cluster但最终没有发布该版本。
ActorSystem.Create
的最佳地点是Global.asax Application_Start()
。ActorSystem
对象的静态引用。有助于确保ActorSystem
本身在长时间运行的应用程序中不会被垃圾收集。/user/
层次结构顶部的actor。此类还应提供ASP.MVC控制器和操作方法可用于Tell
和Ask
操作的actor路径。创建ActorSystem
是一项非常昂贵的操作,因为很多系统级的东西会立刻被激活。在应用程序启动时,最好这样做一次,然后将结果缓存在Application
类中。
创建单个actor实例很便宜 - 您应该能够在ASP.NET MVC操作方法中执行此无问题。如果您再次看到此错误,请告诉我们发生此错误的请求处理过程中的哪个部分以及ASP.NET的版本。
答案 1 :(得分:22)
将ActorSystem保存为某个静态类容器中的共享属性 - 这样您就可以从应用程序的其余部分访问它。演员系统初始化/处理可以通过以下方式完成:
ActorSystem.Create(...)
中使用Application_Start
,并在system.Shutdown()
上使用Application_End
进行处理。Startup.Configuration
方法中创建actor系统,并通过绑定到 host.OnAppDisposing 事件(how-to link)将其关闭。< / LI>
请记住,IIS只会在第一次请求后启动您的Web应用程序,并在闲置一段时间后自动将其拆除。因此,如果您希望Akka actor系统连续运行,请确保您的部署脚本在发布后ping应用程序并设置空闲超时(link)足够长的时间。
第二个选项
分离您的Actor系统逻辑并将其部署,例如,作为Windows服务(或Linux deamon)。打开Akka.Remoting并创建一个代理客户端,它将所有应用程序长期运行的敏感任务转发到外部服务。当您的应用程序逻辑必须连续工作时,类似的解决方案通常用于诸如调度程序或事件总线之类的事情。