Service Fabric 自删除服务

Service Fabric self-deleting service

我想添加一个服务,在系统首次创建时为系统执行一些初始化操作。

我想这将是一个无状态服务(具有集群管理员权限),它应该在完成后自毁。我是 under the impression that exiting the RunAsync function 允许我指示我已完成(或处于错误状态)。但是,它仍然在应用程序的上下文中徘徊,并且看起来很烦人 "active" 当它根本没有做任何事情时。

服务是否可以自行删除?

我想也许我们可以尝试在 OnCloseAsync 覆盖中使用 FabricClient.ServiceManagerDeleteServiceAsync(使用基于服务上下文的参数),但我无法做到证明这可能有效并且感觉有点古怪:

var client = new FabricClient();
await client.ServiceManager.DeleteServiceAsync(new DeleteServiceDescription(Context.ServiceName));

有没有更好的方法?

从 RunAsync 返回将结束 RunAsync 中的代码(表示完成),因此 SF 不会再次启动 RunAsync(例如,如果它返回异常,它会启动)。 RunAsync 完成不会导致 service 被删除。例如,如前所述,该服务可能通过后台工作完成,但仍在侦听传入消息。

关闭服务的最佳方法是调用 DeleteServiceAsync。这可以由服务本身或其他服务完成,也可以从集群外部完成。服务可以自行删除,因此对于已完成工作的服务,我们通常会在 RunAsync 的最后一行看到等待 DeleteServiceAsync,之后该方法就会退出。类似于:

RunAsync(CancellationToken ct)
{
    while(!workCompleted && !ct.IsCancellationRequested)
    {
        if(!DoneWithWork())
        {
            DoWork()
        }

        if(DoneWithWork())
        {
            workCompleted == true;
            await DeleteServiceAsync(...) 
        }
    }
}

目标是确保如果您的服务确实完成了工作,它会自行清理,但不会因为 CancellationToken 可以收到信号的其他原因而触发自己的删除,例如由于以下原因而关闭一些升级或集群资源平衡。

如前所述,从 RunAsync returning 只会结束此方法,但服务将继续 运行,因此不会被删除。

DeleteServiceAsync 当然是要走的路 - 但是它并不像调用它那么简单,因为如果你不小心它会在当前线程上死锁(特别是在本地开发人员集群中)。您还可能会收到一些关于 RunAsync 需要很长时间才能终止的短暂健康警告 and/or 未满足目标副本大小。

无论如何 - 解决方案非常简单 - 只需这样做:

private async Task DeleteSelf(CancellationToken cancellationToken)
{
       using (var client = new FabricClient())
       {
            await client.ServiceManager.DeleteServiceAsync(new DeleteServiceDescription(this.Context.ServiceName), TimeSpan.FromMinutes(1), cancellationToken);
       }
}

然后,在我调用的 RunAsync 方法的最后一行中:

await DeleteSelf(cancellationToken).ConfigureAwait(false);

ConfigureAwait(false) 将有助于解决死锁问题,因为它本质上会 return 到一个新的线程同步上下文 - 即不会尝试 return 到 "caller context"。