- 后端
- 微服务
【免费下载链接】akka.net
Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
本文讲解如何将 Akka.NET 的ActorSystem托管到 Azure PaaS Cloud Service 的 Worker Role 中,涵盖RoleEntryPoint的OnStart/Run/OnStop生命周期与 Actor 系统的启动、阻塞等待、优雅关闭的完整实现,并结合当前仓库中的 Windows Service / Headless Service 示例源码,说明该部署模式与现代BackgroundService宿主模式的对应关系,帮助你在遗留 Azure 项目中正确移植或维护 Akka.NET 宿主代码。
背景:Azure Cloud Service(已弃用)与 Worker Role
首先需要明确一个前提:Azure Cloud Service 如今已大面积弃用(largely deprecated in Azure)。官方文档在文首即以醒目提示标注了这一点。因此本文的定位是:如果你需要阅读、维护或移植基于旧版 Azure PaaS Cloud Service 模板的 Akka.NET 宿主代码(这也是当前文档的原始场景),应当如何理解其结构与生命周期;如果你是在新建项目,则应优先参考后文给出的现代BackgroundService替代方案。
原文档描述的部署模型是:
- 在 Visual Studio 中安装 Azure .NET SDK 后,可使用其提供的项目模板创建一个包含单个空 Worker Role的 Azure PaaS Cloud Service 工程;
- Worker Role 的宿主代码结构与 Windows Service 非常相似——本质上都是"进程宿主 + 顶层用户 Actor"的长驻服务模式;
- 部署到云端之前,可以使用Azure Compute Emulator在本地对 Worker Role 实现进行测试与调试。
快速上手方式是:创建一个简单的 Worker Role,在其RunAsync()方法中启动顶层用户 Actor。下面给出完整实现。
WorkerRole.cs 完整实现
using Akka.Actor; namespace MyActorWorkerRole { public class WorkerRole : RoleEntryPoint { private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false); private ActorSystem _actorSystem; public override bool OnStart() { // Setup the Actor System _actorSystem = ActorSystem.Create("MySystem"); return (base.OnStart()); } public override void OnStop() { this.cancellationTokenSource.Cancel(); this.runCompleteEvent.WaitOne(); // Shutdown the Actor System _actorSystem.Shutdown(); base.OnStop(); } public override void Run() { try { this.RunAsync(this.cancellationTokenSource.Token).Wait(); } finally { this.runCompleteEvent.Set(); } } private async Task RunAsync(CancellationToken cancellationToken) { // Create an instance to the top-level user Actor var workerRoleActor = _actorSystem.ActorOf<WorkerRoleActor>("WorkerRole"); // Send a message to the Actor workerRoleActor.Tell(new WorkerRoleMessage("Hello World!")); while (!cancellationToken.IsCancellationRequested) { await Task.Delay(1000, cancellationToken); } } } }逐段解读:Azure 宿主与 Akka 生命周期的衔接
这段代码虽然简短,但每个成员都承担了明确的职责,值得逐段拆解:
OnStart()—— 创建 ActorSystemAzure SDK 的RoleEntryPoint基类在实例化 Worker Role 后调用OnStart()。这里创建名为"MySystem"的ActorSystem(对应源码中ActorSystem.Create工厂方法,参见 ActorSystem),然后调用base.OnStart()让 Azure 运行时完成自身初始化。注意OnStart()返回false会导致角色实例启动失败,所以务必保持return base.OnStart()。Run()—— 阻塞宿主线程直到取消Azure 要求Run()保持阻塞以维持 Worker Role 存活。实现上用RunAsync(...).Wait()同步等待异步主循环;finally中runCompleteEvent.Set()释放一个ManualResetEvent,供OnStop()感知"Run 已完成",从而保证关闭时序。RunAsync()—— 启动顶层 Actor 并保活_actorSystem.ActorOf<WorkerRoleActor>("WorkerRole")派生出顶层用户 ActorWorkerRole(路径为akka://MySystem/user/WorkerRole);- 通过
Tell(new WorkerRoleMessage("Hello World!"))向其发送第一条消息; - 随后进入
while (!cancellationToken.IsCancellationRequested)保活循环,Task.Delay(1000, cancellationToken)让线程在等待中让出,且取消令牌触发时循环可立即退出——这是整个"进程保活"的关键。
OnStop()—— 按序优雅关闭关闭顺序是这段代码最重要的语义,共三步:cancellationTokenSource.Cancel():通知RunAsync主循环退出;runCompleteEvent.WaitOne():阻塞等待Run()的finally分支执行完毕,确认主循环已停止;_actorSystem.Shutdown():关闭 Actor 系统。
从源码结构看,
ActorSystem的Shutdown与Terminate语义不同:Shutdown在系统终止前会先运行 CoordinatedShutdown 的协调关闭流程(若已启用),再逐步停止 Actor;对仅含少量无状态 Actor 的 Worker Role 而言,直接Shutdown()已足够。仓库中更完善的 Headless Service 示例则展示了关闭时的推荐写法——显式触发协调关闭:// src/examples/HeadlessService/AkkaHeadlesssService/AkkaService.cs await CoordinatedShutdown.Get(_actorSystem).Run(CoordinatedShutdown.ClrExitReason.Instance);如果你移植该 Worker Role 且启用了 Cluster/持久化等模块,建议照此处理,可保证集群成员、消息等在 CLR 退出前被妥善处理。
本地调试:Azure Compute Emulator
在部署到 Azure 之前,原文档指出 Worker Role 实现可以先用 Azure Compute Emulator 在本地验证:它在本地模拟 Cloud Service 的启动、停止等生命周期事件,因此可以完整走到OnStart→Run→OnStop三条路径,等价于验证上面整个生命周期代码。调试要点:
- 关注
OnStart()是否返回true——这是角色启动成功的唯一信号; - 关注
OnStop()中"取消 → 等待 → 关闭"的时序是否都实际执行(可通过 ActorSystem 的终止日志确认Shutdown()被调用)。
现代替代:BackgroundService / IHostedService 宿主模式
由于 Cloud Service 已弃用,新建项目不应再使用RoleEntryPoint,而是采用Microsoft.Extensions.Hosting的BackgroundService(IHostedService)模式——这正是原文档所说的"与 Windows Service 实现非常相似"的当代形态。当前仓库提供了两套可直接对照的示例。
示例一:Windows Service(BackgroundService + DI)
位于 src/examples/WindowsService/AkkaWindowsService:
Program.cs通过Host.CreateDefaultBuilder+UseWindowsService注册宿主:
using IHost host = Host.CreateDefaultBuilder(args) .UseWindowsService(options => { options.ServiceName = ".NET Joke Service"; }) .ConfigureServices(services => { services.AddHostedService<AkkaService>(); services.AddHttpClient<JokeService>(); }) .Build(); await host.RunAsync();AkkaService(BackgroundService子类)把 Worker Role 示例中的职责一一映射到了新的宿主模型上:
public sealed class AkkaService : BackgroundService { private readonly ILogger<AkkaService> _logger; private readonly JokeService _jokeService; private readonly ActorSystem _actorSystem; private readonly IActorRef _actorRef; public AkkaService(JokeService jokeService, ILogger<AkkaService> logger, IServiceProvider serviceProvider) { _jokeService = jokeService; _logger = logger; var bootstrap = BootstrapSetup.Create(); // enable DI support inside this ActorSystem, if needed var diSetup = DependencyResolverSetup.Create(serviceProvider); // merge this setup (and any others) together into ActorSystemSetup var actorSystemSetup = bootstrap.And(diSetup); // start ActorSystem _actorSystem = ActorSystem.Create("akka-system", actorSystemSetup); _actorRef = _actorSystem.ActorOf(MyActor.Prop()); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { var joke = await _jokeService.GetJokeAsync(); _logger.LogWarning(joke); await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken); _actorRef.Tell(joke); } } }对照关系非常清晰:
Worker Role(RoleEntryPoint) | BackgroundService(现代宿主) |
|---|---|
OnStart()中ActorSystem.Create | 构造函数中创建ActorSystem,并可叠加DependencyResolverSetup启用 Actor 内 DI(来自 Akka.DependencyInjection) |
RunAsync()的保活循环 | ExecuteAsync(stoppingToken)的主循环 |
CancellationTokenSource.Cancel() | 宿主框架下发的stoppingToken |
OnStop()中_actorSystem.Shutdown() | 由IHostedService.StopAsync或CoordinatedShutdown处理 |
该示例的工程文件 AkkaWindowsService.csproj 显示其依赖Microsoft.Extensions.Hosting.WindowsServices(注册为 Windows 服务)与Microsoft.Extensions.Http(JokeService使用的 HTTP 客户端),并通过ProjectReference引用core/Akka与contrib/dependencyinjection/Akka.DependencyInjection。
示例二:Headless Service(IHostedService + 协调关闭)
位于 src/examples/HeadlessService/AkkaHeadlesssService,展示了与 Azure Worker Role 场景最贴近的"无界面后台服务"写法:
public Task StartAsync(CancellationToken cancellationToken) { var bootstrap = BootstrapSetup.Create(); var diSetup = DependencyResolverSetup.Create(_serviceProvider); var actorSystemSetup = bootstrap.And(diSetup); // start ActorSystem _actorSystem = ActorSystem.Create("headless-service", actorSystemSetup); _actorRef = _actorSystem.ActorOf(HeadlessActor.Prop()); // add a continuation task that will guarantee shutdown of application if ActorSystem terminates _actorSystem.WhenTerminated.ContinueWith(_ => { _applicationLifetime.StopApplication(); }); return Task.CompletedTask; } public async Task StopAsync(CancellationToken cancellationToken) { // strictly speaking this may not be necessary - terminating the ActorSystem would also work // but this call guarantees that the shutdown of the cluster is graceful regardless await CoordinatedShutdown.Get(_actorSystem).Run(CoordinatedShutdown.ClrExitReason.Instance); }相比 Worker Role 示例,它多了两个值得移植时吸收的细节:
_actorSystem.WhenTerminated.ContinueWith(...)调用_applicationLifetime.StopApplication():一旦 ActorSystem 因任何原因终止(如 Actor 抛出未捕获错误导致系统关闭),宿主进程随之停止,避免"进程活着但 Actor 已死"的僵尸状态;StopAsync中显式CoordinatedShutdown.Get(...).Run(CoordinatedShutdown.ClrExitReason.Instance):如源码注释所述,"严格来说终止 ActorSystem 也可以,但该调用可保证关闭(含集群场景)是优雅的"。
小结
- Azure Cloud Service 的 Worker Role 宿主模式 =
OnStart建系统、Run保活、OnStop取消-等待-关闭;完整参考实现见 docs/articles/deployment/azure-cloud-service.md; - 该文档已标注 Cloud Service 大面积弃用,新建宿主请直接使用
BackgroundService/IHostedService,参考仓库示例 src/examples/WindowsService 与 src/examples/HeadlessService,部署场景总览见 docs/articles/deployment/index.md; - 无论哪种宿主,关闭路径的核心都不变:先停主循环,再关闭
ActorSystem,涉及集群/持久化时优先走CoordinatedShutdown。
- 后端
- 微服务
【免费下载链接】akka.net
Canonical actor model implementation for .NET with local + distributed actors in C# and F#.
相关推荐
Cloud Custodian Azure 容器宿主(Azure Container Host)完整指南:架构、策略模式与部署实战
Cloud Custodian Azure 容器宿主(Azure Container Host)完整指南:架构、策略模式与部署实战 Cloud Custodia
云原生运维安全huggingface_hub Inference Endpoints 编程式管理实战:从部署、推理到生命周期
huggingface_hub Inference Endpoints 编程式管理实战:从部署、推理到生命周期 Hugging Face Inference E
开发工具CLI机器学习Akka.NET 依赖注入实战指南:从 Akka.DependencyInjection 到 Actor 生命周期管理
Akka.NET 依赖注入实战指南:从 Akka.DependencyInjection 到 Actor 生命周期管理 本文围绕 Akka.NET 官方推荐的依
后端微服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考