我正在使用IReliableQueue的Service Fabric应用程序中工作。对于该系统的用例,使用IReliableConcurrentQueue是有意义的,并且进行了一些本地测试(即,基本上只是通过更改代码以使用IReliableConcurrentQueue而不是IReliableQueue-队列名称不变),可以显着提高性能。但是,我担心在生产系统中进行更改(即升级)会带来什么影响。关于这些注意事项,我找不到任何文档或在线问题(除非我只是想念他们)。例如,在此系统中,现有的IReliableQueue几乎总是具有项目。那么,当我升级SF应用程序时,这些数据会怎样?是否可以在IReliableConcurrentQueue中出队?还是会丢失数据?我知道我可以“尝试一下”,但想看看外面是否有人这样做或可以提供指向现有资源的指针。谢谢!
答案 0 :(得分:2)
对不起,我想晚回答了。(您可能已经不需要了,但仍然需要)。
当我们在GetOrAddAsync
上调用IReliableStateManager
方法时,我们不是在检索存储值的接口,而是实际上创建了一个可靠集合的实例。这基本上意味着我们指定的接口类型非常重要。
请注意以下事项:
服务v。1.0
// Somewhere in RunAsync for example
await this.StateManager.GetOrAddAsync<IReliableQueue<long>>("MyCollection")
然后在下一个版本中这样做:
服务v.1.1
// Somewhere in RunAsync for example
await this.StateManager.GetOrAddAsync<IReliableConcurrentQueue<long>>("MyCollection")
将引发异常:
返回的类型为Microsoft.ServiceFabric.Data.Collections.DistributedQueue`1 [System.Int64]的可靠对象不能转换为请求的类型Microsoft.ServiceFabric.Data.Collections.IReliableConcurrentQueue`1 [System.Int64]
然后:
System.ExecutionEngineException:'引发了类型为'System.ExecutionEngineException'的异常。'
上面的异常看起来像个错误,所以我填写了one。
这将发生。
有很多方法可以克服这个问题。
这是最明显的一个:
示例
var migrate = false; // This flag indicates whether the migration was already done.
var migrateValues = new List<long>();
var applicationFlags = await this.StateManager
.GetOrAddAsync<IReliableDictionary<string, bool>>("application-flags");
using (var transaction = this.StateManager.CreateTransaction())
{
var flag = await applicationFlags
.TryGetValueAsync(transaction, "queue-to-concurrent-queue-migration");
if (!flag.HasValue || !flag.Value)
{
var queue = await this.StateManager
.GetOrAddAsync<IReliableQueue<long>>("value-collection");
for (;;)
{
var c = await queue.TryDequeueAsync(transaction);
if (!c.HasValue)
{
break;
}
migrateValues.Add(c.Value);
}
migrate = true;
}
}
if (migrate)
{
await this.StateManager.RemoveAsync("value-collection");
using (var transaction = this.StateManager.CreateTransaction())
{
var concurrentQueue = await this.StateManager
.GetOrAddAsync<IReliableConcurrentQueue<long>>("value-collection");
foreach (var i in migrateValues)
{
await concurrentQueue.EnqueueAsync(transaction, i);
}
await applicationFlags.AddOrUpdateAsync(
transaction,
"queue-to-concurrent-queue-migration",
true,
(s, b) => true);
}
await transaction.CommitAsync();
}
请注意,此代码仅是一个说明性示例,应在将其应用于实际应用程序之前进行正确的测试。