我试图了解服务架构的一些最佳做法。
如果我有一个由Web服务或其他机制添加的队列和后端任务来处理该队列,那么在后台处理长时间运行操作的最佳方法是什么。
两种方式都有点不对劲,但如果有更好的方法,我就无法解决问题。
答案 0 :(得分:13)
一种选择是在RunAsync中处理队列,类似于:
protected override async Task RunAsync(CancellationToken cancellationToken)
{
var store = await StateManager.GetOrAddAsync<IReliableQueue<T>>("MyStore").ConfigureAwait(false);
while (!cancellationToken.IsCancellationRequested)
{
using (var tx = StateManager.CreateTransaction())
{
var itemFromQueue = await store.TryDequeueAsync(tx).ConfigureAwait(false);
if (!itemFromQueue.HasValue)
{
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
continue;
}
// Process item here
// Remmber to clone the dequeued item if it is a custom type and you are going to mutate it.
// If success, await tx.CommitAsync();
// If failure to process, either let it run out of the Using transaction scope, or call tx.Abort();
}
}
}
关于克隆已出列项目的评论,如果要改变它,请在此处的“建议”部分下查看: https://azure.microsoft.com/en-us/documentation/articles/service-fabric-reliable-services-reliable-collections/
可靠集合(队列和字典)的一个限制是,每个分区只有1个并行度。因此,对于高活动队列,它可能不是最佳解决方案。这可能是您遇到的问题。
我们一直在做的是在写入量非常低的情况下使用ReliableQueues。对于更高吞吐量的队列,我们需要耐用性和规模,我们正在使用ServiceBus主题。这也为我们提供了这样的优势:如果一个服务仅因为具有ReliableQueue而处于Stateful状态,那么它现在可以变为无状态。虽然这会增加对第三方服务(在本例中为ServiceBus)的依赖性,但这可能不适合您。
另一种选择是创建一个持久的pub / sub实现来充当队列。我之前已经完成了使用演员的测试,这似乎是一个可行的选择,没有花太多时间,因为我们根据ServiceBus没有任何问题。这是关于Pub/sub pattern in Azure Service Fabric
的另一个问题答案 1 :(得分:3)
如果非常慢,则使用2个队列..一个是快速的,您可以在不中断的情况下存储工作,而缓慢的则可以处理它。 RunAsync用于将消息从快速移动到慢速。