我有一个使用IReliableConcurrentQueue存储状态的有状态服务。我正在使用无状态ASP.NET核心服务来公开两个REST端点。
GET端点从指定的IReliableConcurrentQueue获取指定数量的项目。它还会在返回之前写入同一事务中的单独可靠并发队列。 POST端点接收项目列表并将它们添加到IReliableConcurrentQueue。
当我在调试模式下从本地运行Visual Studio服务时,当我反复点击一个端点(GET或POST)时,它可以正常工作而没有任何问题。
当我同时点击两个端点时,经过3或4次点击(有时是10次)后,服务停止响应,我看到超时例外。
REST端点(无状态服务)
[HttpGet]
[Route("{number}/{queueName}")]
public async Task<IEnumerable<QueueItem>> Get(int number, string queueName)
{
IEnumerable<QueueItem> items = await statefulServiceProxy.GetItems(number, queueName);
return items;
}
[HttpPost]
[Route("item")]
public async Task Set([FromBody]IEnumerable<Item> items)
{
await statefulServiceProxy.SetItem(items);
}
有状态服务
始终陷入ReadAndLockItems()或SetItem()中的CommitAsync函数。
public async Task<IEnumerable<QueueItem>> GetItems(int number, string queueName)
{
var items = await this.ReadAndLockItems(number, queueName);
return items;
}
private async Task<IEnumerable<QueueItem>> ReadAndLockItems(int number, string queueName)
{
var itemQueue = await this.StateManager.GetOrAddAsync<IReliableConcurrentQueue<QueueItem>>(queueName);
var lockQueue = await this.StateManager.GetOrAddAsync<IReliableConcurrentQueue<QueueItem>>("LockQueue");
List<QueueItem> results = new List<QueueItem>();
using (var tx = this.StateManager.CreateTransaction())
{
for (int i = 0; i < number; i++)
{
var element = await itemQueue.TryDequeueAsync(tx);
if (element.HasValue)
{
results.Add(element.Value);
}
}
results.ToList().ForEach(async r =>
{
await lockQueue.EnqueueAsync(tx, r);
});
await tx.CommitAsync(); // This is where it gets stuck.
}
return results;
}
public async Task SetItem(IEnumerable<Product> products)
{
var productQueue = await this.StateManager.GetOrAddAsync<IReliableConcurrentQueue<Product>>("ProductQueue");
using (var tx = this.StateManager.CreateTransaction())
{
foreach (Product p in products)
{
await productQueue.EnqueueAsync(tx, p);
}
await tx.CommitAsync(); // Sometimes it gets stuck here. It's not consistent. Either in this function or the above one.
}
}
我检查了这个Post并尝试了那里提到的更改。它还不起作用。
例外详情:
System.TimeoutException: This can happen if message is dropped when service is busy or its long running operation and taking more time than configured Operation Timeout.
at Microsoft.ServiceFabric.Services.Communication.Client.ServicePartitionClient`1.<InvokeWithRetryAsync>d__24`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
我使用收藏品和相关交易的方式有什么问题吗?