将IReliableQueue更改为IReliableConcurrentQueue对现有部署有什么影响?

时间:2019-02-08 16:37:12

标签: azure-service-fabric

我正在使用IReliableQueue的Service Fabric应用程序中工作。对于该系统的用例,使用IReliableConcurrentQueue是有意义的,并且进行了一些本地测试(即,基本上只是通过更改代码以使用IReliableConcurrentQueue而不是IReliableQueue-队列名称不变),可以显着提高性能。但是,我担心在生产系统中进行更改(即升级)会带来什么影响。关于这些注意事项,我找不到任何文档或在线问题(除非我只是想念他们)。例如,在此系统中,现有的IReliableQueue几乎总是具有项目。那么,当我升级SF应用程序时,这些数据会怎样?是否可以在IReliableConcurrentQueue中出队?还是会丢失数据?我知道我可以“尝试一下”,但想看看外面是否有人这样做或可以提供指向现有资源的指针。谢谢!

1 个答案:

答案 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();
}

请注意,此代码仅是一个说明性示例,应在将其应用于实际应用程序之前进行正确的测试。