我正在研究 ServiceFabric 场景,在该场景中我生成无状态服务的实例以运行某些任务。我使用 FabricClient.ServiceManager.CreateServiceAsync 创建实例,这按预期工作。
一旦我的任务完成,我希望我生成的服务能够自行关闭,因此我使用 FabricClient.ServiceManager.DeleteServiceAsync。
服务按预期关闭,但是我的调试器在这一行的 Program.Main 类中停止:
// Prevents this host process from terminating so services keep running.
Thread.Sleep(Timeout.Infinite);
没有异常(exception),我可以点击继续,并且我的应用程序在发生这种情况后按预期运行。但我必须错过一个步骤才能正确关闭我的服务。有没有“最佳实践”方法来做到这一点?
我考虑过让我的服务请求另一个服务(例如托管人)来处理关闭,但这对我来说似乎开销太大。
我的偏好是服务本身应该能够自行处理该问题,除非事实证明这是一种不好的做法。
更新:
我将服务的删除移至 ManagerService 来处理关闭它的问题,但我的调试器仍然像以前一样停止在已删除服务的 Program.Main 上。我还添加了屏幕截图(如下)。
如果我点击继续,一切都会按预期运行。这是因为调试器仍然连接并且不知道该服务不再在结构下运行吗?可以忽略它并将其发布到生产中吗?
更新2
我收到很多反馈,因为我运行了调试器,所以一旦我不再在结构上运行该特定服务的实例,它就会出现问题,这是预期的行为。由于如果我从服务本身或外部服务中删除服务,我会得到相同的行为,因此我想了解有关此场景的最佳实践的一些想法...
理想情况下,让服务自行清理是最好的,因为不依赖于外部服务,它不那么复杂,并且需要编写的代码也更少(并且出错的可能性也更少)。
除了必须调用 FabricClient 之外,当然还有最佳实践吗?是否存在某种“关闭”覆盖? CancellationToken 在这里起作用吗?
最佳答案
您所描述的行为是预期的(如果您在 main 中启动调试器,则调试器可能一直处于该超时线上)。宿主进程的生命周期与其内部托管服务的生命周期不同。
当主机进程为空时,Service Fabric 会在关闭之前等待一段时间,因为服务主机在生产中通常不会为空,并且会尝试避免创建和销毁进程的开销(这会减慢后续服务创建的速度) )。
默认情况下,Service Fabric 大约每分钟检查一次进程是否为空,然后将其标记为关闭,然后每隔 10 分钟左右进行一次扫描并关闭空进程,因此您可以看到空进程持续存在大约11分钟,如果你把握得恰到好处的话。
关于c# - 从 Service Fabric 内部关闭 StatelessService 实例的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42683516/