【问题标题】:Service Fabric self-deleting serviceService Fabric 自删除服务
【发布时间】:2018-10-30 23:25:51
【问题描述】:

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

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

服务是否可以自行移除?

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

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

有没有更好的办法?

【问题讨论】:

  • Afaik 不是。完成 runasync 不是服务的触发器,因为它与打开通信侦听器并行运行。因此,您的想法可能是目前最好的方法。:在 runasync 中尝试删除自身。或者使用外部服务来监控完成并让它删除它(因为我不知道服务是否可以删除自己)

标签: service-fabric-stateless azure-service-fabric


【解决方案1】:

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

关闭服务的最佳方法是调用 DeleteServiceAsync。这可以由服务本身或其他服务完成,也可以从集群外部完成。服务可以自行删除,因此对于工作完成的服务,我们通常将 await DeleteServiceAsync 视为 RunAsync 的最后一行,之后该方法就退出了。比如:

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    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) 将有助于解决死锁问题,因为它本质上将返回到新的线程同步上下文 - 即不尝试返回“调用者上下文”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-09
      • 2018-07-24
      • 2017-10-03
      • 2017-12-27
      • 2016-03-25
      • 2017-11-08
      • 2017-01-16
      • 2018-03-30
      相关资源
      最近更新 更多