我在 ASP.NET 年创建了一个使用 RESTful API 的服务,托管在 IIS 中。在此服务中,我想创建一个带有 Akka.NET 的演员系统。
创建演员系统后:
var actorSystem = ActorSystem.Create("myActorSystem");
引发以下异常:
参与者系统System.Web 中发生了类型为"System.InvalidOperationException"的第一次机会异常.dll 其他信息:此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,也可以在页面生命周期中的某些事件期间启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ 页面异步="true" %>。此异常还可能表示尝试调用"异步 void"方法,该方法在请求处理 ASP.NET 中通常不受支持。相反,异步方法应返回一个 Task,调用方应等待它。
本质上是一个并发系统,参与者之间交换异步消息。如此处所述,此执行组件系统将无法在 IIS 关闭 AppDomain 后幸存下来,这可能就是引发上述异常的原因。
本文介绍如何在 ASP.NET 中运行后台任务。但是,我不明白如何将它用于我的 actor 系统,因为我无法控制可能由 Akka.NET 创建的后台任务的生命周期。
有没有办法做到这一点,或者我应该放弃在 ASP.NET 应用程序中使用Actor系统的想法?
编辑:我还在Stackoverflow上看到了一个关于使用Akka实现REST服务的问题。欢迎任何关于类似于 Spray 工具包的解决方案的建议,但 Akka.NET 工作。
我在 ASP.NET MVC 应用程序中使用了 Akka.NET 和 Akka.Remote,这些应用程序在 EC2 上每秒执行多达 1000 个请求 - 所以我将分享一些我用来成功启动和运行的提示和技巧。有一个原型版本,甚至使用Akka.Cluster,但最终没有发布该版本。
- 打电话给
ActorSystem.Create
的最佳地点是在Global.asaxApplication_Start()
内。 - 使用静态字段或属性,挂在 Global.asax 本身中对
ActorSystem
对象的静态引用。帮助确保ActorSystem
本身不会在长时间运行的应用程序中被垃圾回收。 - 创建一个单独的静态帮助程序类来初始化应用程序所需的任何顶级参与者,即
/user/
层次结构顶部的参与者。此类还应提供 ASP 的执行组件路径。MVC 控制器和操作方法可用于Tell
和Ask
操作。
创建ActorSystem
是一个有点昂贵的操作,因为许多系统级的东西会同时启动。最好在应用程序启动时执行此操作一次,然后仅在Application
类中缓存结果。
创建单个参与者实例很便宜 - 您应该能够在 ASP.NET MVC 操作方法中做到这一点。如果您再次看到此错误出现,请告诉我们此错误发生在请求处理过程中的哪个部分以及 ASP.NET 的版本。
编辑:添加了一些有关如何在 ASP.NET Core上执行此操作的更新指南
https://petabridge.com/blog/akkadotnet-aspnetcore/
将 ActorSystem 作为共享属性保留在某个静态类容器中 - 这样您就可以从应用程序的其余部分访问它。Actor系统初始化/处置可以通过以下方式完成:
- Global.asax
- - 在 Global.asax
Application_Start
中使用ActorSystem.Create(...)
,并在Application_End
上用system.Shutdown()
处理。 - OWIN - 在 OWIN 的
Startup.Configuration
方法中创建 actor 系统,并通过绑定到主机将其关闭。OnAppDisposposing 事件(操作方法链接)。
请记住,IIS 仅在首次请求后启动 Web 应用,并在空闲一段时间后自动将其关闭。因此,如果您希望 Akka actor 系统连续运行,请确保您的部署脚本将在发布后 ping 应用程序并设置空闲超时(链接)足够长的时间。
第二种选择
分离您的Actor系统逻辑并将其部署,例如,作为Windows服务(或Linux deamon)。为其打开 Akka.Remoting 并创建一个代理客户端,该客户端会将所有应用程序长时间运行的敏感任务转发到外部服务。类似的解决方案通常用于调度程序或事件总线等,此时应用程序逻辑必须连续工作。