从StateManager正确初始化ReliableCollection

时间:2018-11-29 08:50:30

标签: service-fabric-stateful azure-service-fabric

有人对以下两个伪模式中的哪一个是实例化/利用有状态服务结构服务中的可靠集合的正确方法有任何见解吗?具体来说,想知道一种方法是否更高效,更消耗内存,甚至更容易出错。

方法1(从StateManager的方法内部获取实例):

public class MyService : IService {

  public async Task<string> GetSomeValueAsync(string input){
    var reliableDic = await StateManager.GetOrAddAsync<IReliableDictionary<string, string>>(StateKey);
    var result = await reliableDic.TryGetValue(input);
    return result.HasValue ? result.Value : null;
  }
}

方法2(将集合存储为类中的成员变量)

public class MyService : IService {
  private bool _isInitialized;
  private readonly object _lock = new object();
  private IReliableDictionary<string, string> _dictionary;

  private async Task Initialize(){
     if (_isInitialized){
       return;
     }

     lock(_lock){
       if (_isInitialized){
         return;
       }

       _dictionary = await StateManager.GetOrAddAsync<IReliableDictionary<string, string>>(StateKey);
       _isInitialized = true;
     }
  }     

  public async Task<string> GetSomeValueAsync(string input){
    await Initialize();
    var result = await _dictionary.TryGetValue(input);
    return result.HasValue ? result.Value : null;
  }
}

因此,方法1在每种方法中都从StateManager中获取字典,而方法2进行了惰性初始化检查,然后使用类成员。

我们看到的大多数示例都在使用方法1,但是方法2背后的想法是将可靠的字典存储在实例字段中,并避免每种方法中的StateManager.GetOrAddAsync命中以及对{{ 1}},这对于采用多种方法和可能更可靠的集合的大型服务可能是有益的。

很乐意了解这两种方法中是否存在任何陷阱或效率低下(显然,方法2更冗长,并且使用了更多的代码行,但这并不是主要问题)。

1 个答案:

答案 0 :(得分:2)

实际上,没有真正的理由来缓存StateManager.GetOrAddAsync的结果,除了保存Task对象的内存分配或在不适合使用StateManager的地方使其可用。

原因很简单-StateManager已经为您缓存了IRealiableState的实例。因此,每次您执行StateManager.GetOrAddAsync时,它都会返回相同的实例(here是Microsoft的官方回答)。

您还可以使用非常简单的测试(ctrue)自己检查它:

var q1 = stateManager.GetOrAddAsync<IReliableDictionary<string, string>>("MyDict")
                     .GetAwaiter().GetResult();
var q2 = stateManager.GetOrAddAsync<IReliableDictionary<string, string>>("MyDict")
                     .GetAwaiter().GetResult();
var c = q1 == q2;