我想添加一个服务,在系统首次创建时为系统执行一些初始化操作。
我认为这将是一个无状态服务(具有集群管理员权限),当它完成时它应该自毁。我under the impression that exiting the RunAsync
function允许我指出我已经完成(或处于错误状态)。然而,它仍然在应用程序的上下文中徘徊,并且当它根本没有做任何事情时,看起来像是“活跃的”。
服务是否可以自行删除?
我想也许我们可以尝试在FabricClient.ServiceManager
覆盖中使用DeleteServiceAsync
的{{1}}(使用基于服务上下文的参数),但我无法证明可能会工作,感觉有点时髦:
OnCloseAsync
有更好的方法吗?
答案 0 :(得分:3)
从RunAsync返回将结束RunAsync中的代码(指示完成),因此SF不会再次启动RunAsync(例如,如果它返回异常,则会发生)。 RunAsync完成不会导致服务被删除。如上所述,例如,服务可以通过后台工作完成,但仍然可以监听传入的消息。
关闭服务的最佳方法是调用DeleteServiceAsync。这可以由服务本身或其他服务完成,也可以从群集外部完成。服务可以自行删除,因此对于工作完成的服务,我们通常会看到等待DeleteServiceAsync作为RunAsync的最后一行,之后该方法才会退出。类似的东西:
RunAsync(CancellationToken ct)
{
while(!workCompleted && !ct.IsCancellationRequested)
{
if(!DoneWithWork())
{
DoWork()
}
if(DoneWithWork())
{
workCompleted == true;
await DeleteServiceAsync(...)
}
}
}
目标是确保如果您的服务实际完成了工作,它会自行清理,但不会因为CancellationToken可以发出信号的其他原因而触发自己的删除,例如由于关闭而关闭一些升级或集群资源平衡。
答案 1 :(得分:1)
如前所述,从RunAsync返回仅将结束此方法,但是该服务将继续运行,因此不会被删除。
beforeunload
当然是要走的路-但是它并不像调用它那样简单,因为如果您不小心,它将死锁在当前线程上(尤其是在本地开发人员集群中)。您还可能会收到一些短期运行状况警告,提示有关RunAsync需要很长时间终止和/或未达到目标副本大小。
在任何情况下-解决方案都非常简单-只需执行以下操作:
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "If you refresh your page you will need to use the link provided by the coordinator to access again. Do you want to continue?";
e.returnValue = confirmationMessage;
return confirmationMessage;
});
然后,在我的RunAsync方法的最后一行中调用:
DeleteServiceAsync
private async Task DeleteSelf(CancellationToken cancellationToken)
{
using (var client = new FabricClient())
{
await client.ServiceManager.DeleteServiceAsync(new DeleteServiceDescription(this.Context.ServiceName), TimeSpan.FromMinutes(1), cancellationToken);
}
}
将有助于解决死锁问题,因为它实际上将返回到新的线程同步上下文-即,不要尝试返回“调用者上下文”。