问题描述
- 我正在运行Service Fabric中托管的.NET Core 2.2 Web API。
- 该API的部分职责是监视外部FTP存储中是否有新的传入文件。
- 每个文件都将触发具有处理逻辑的调解器
Command
。 - 我已经实现了基于https://docs.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice和https://blog.maartenballiauw.be/post/2017/08/01/building-a-scheduled-cache-updater-in-aspnet-core-2.html的混合解决方案。本质上,这是一个
IHostedService
实现,已在此API的Startup.cs
中注册。它基本上是在进程中运行的后台服务。
关于这个问题。上面的解决方案在1节点群集上可以正常工作,但是在5节点群集上运行时会导致“重复项”被处理。问题在于这样的事实:在5节点群集上,当然有5个相同的ScheduledTasks
正在运行,并且都将以相同的方式访问FTP上的 same 文件。时间。
我已经意识到,这在某种程度上是由于关注点分离不当引起的-aka API不应对此负责,而应该由一个完全独立的进程来处理。
这使我了解到服务结构(有状态,无状态,演员和托管来宾Exe's)支持的不同服务。 Actor
似乎是唯一运行单线程的服务器,即使在5节点群集上也是如此。另外,Actor
似乎不太适合这种情况,因为它需要被触发。就我而言,我基本上需要一个守护进程,该守护进程始终按计划运行。如果我没记错的话,其他有状态/无状态服务也将与5个“克隆”一起运行,并导致与我目前相同的问题。
我猜我的问题是:如何使用 Service Fabric 进行高效的后台处理并避免这些多线程/重复问题?预先感谢您的任何投入。
解决方法
在Farbic服务中,与演员有2种选择:
您可以使用状态来确定actor是否已处理您的ftp文件。
看看this blog post,看看他们如何使用提醒来每30秒运行一次。
重要的是,actor中的代码允许reantrancy。 基本上因为参与者是可靠的,所以您的代码可能会多次执行,并在执行过程中被取消。
代替这样做:
public void Method()
{
_ftpService.Process(file);
}
考虑这样做:
public void Method(int fileId)
{
if (_ftpService.IsNotProcessed(fileId))
{
_ftpService.Process(file);
_ftpService.SetProcessed(fileId);
}
}
如果您的演员无法处理,您可能要检查您是否正在处理代码中的取消令牌。我从来没有遇到过这个问题,但是我们正在使用Autofac.ServiceFabric的autofac向RegisterActor<T>()
注册参与者,并且在大多数逻辑中都有取消令牌。 CancellationTokenSource的文档也可以为您提供帮助。
例子
public Ctor()
{
_cancelationTokenSource = new CancellationTokenSource();
_cancellationToken= _cancelationTokenSource.Token;
}
public async Task SomeMethod()
{
while(/*condition*/)
{
_cancellationToken.ThrowIfCancellationRequested();
/*Other code*/
}
}
protected override async Task OnDeactivateAsync()
{
_cancelationTokenSource.Cancel();
}