2016-04-26 71 views
2

我正在Azure服務結構中創建一個actor服務。部署到Azure時,它似乎首先起作用。可以添加和返回文本(演員由Web API前端),但在空閒一段時間後,GetTextsAsync將返回一個空集合。爲什麼演員的國家失去了?

編輯: 我已經更新了代碼,以檢查添加它之前狀態是否存在,但它不能解決問題。

[StatePersistence(StatePersistence.Persisted)] 
public class TextActor : Actor, ITextActor 
{ 
    protected override async Task OnAactivateAsync() 
    { 
     if(!await StateManager.ContainsStateAsync("State")) 
     { 
      await this.StateManager.TryAddStateAsync<List<string>>("State", new List<string>()); 
     } 

    } 

    public async Task AddTextAsync(string text) 
    { 
     var texts = await this.StateManager.GetStateAsync<List<string>>("State"); 

     texts.Add(text); 

     await this.StateManager.SetStateAsync("State", texts); 
    } 

    public async Task<List<string>> GetTextsAsync() 
    { 
     return await this.StateManager.GetStateAsync<List<string>>("State"); 
    } 
} 

編輯2: 看起來好像演員本身被替換。我修改了actor以返回其ActorId,並且當文本列表消失時,ActorId也被替換爲新的。

我遵循VoiceMailBox示例中的模式,其中actor是在控制器中靜態創建的。這是問題嗎?

public class TextsController : ApiController 
{ 
    private static Uri serviceUri = new Uri("fabric:/TextApp/TextActorService"); 
    private static ActorId actorId = ActorId.CreateRandom(); 
    private static ITextActor textActor = ActorProxy.Create<ITextActor>(actorId, serviceUri);   


    [HttpGet] 
    public async Task<IHttpActionResult> GetTexts() 
    { 
     var texts = await textActor.GetTextsAsync(); 
     return Ok(texts);    
    } 

    //Methods omitted 
} 
+1

重新編輯2:行'private static ActorId actorId = ActorId.CreateRandom();'似乎是一個壞主意。您的每個WebApi無狀態服務實例都會以不同的'ActorId'結尾。即使只有一個實例,如果要重新啓動,替換實例對於「textActor」將具有不同的「ActorId」。我會去使用一個常量'ActorId',看看是否解決了這個問題。就像'私人靜態ActorId actorId =新的ActorId(0);' –

+0

@NickBarrett,這是我的主要問題。 – Landrew

回答

3

這是因爲您在OnActivate()方法具有代碼 - 它的狀態重置爲一個新的列表。

OnActivate()方法可以在一個actor上被多次調用 - 它不僅在你第一次創建一個特定的actor時被調用。如果演員在一段時間內沒有使用,那麼它將被取消激活(並調用OnDeactivateAsync()方法)。但是當對演員發出新的呼叫時,它會再次激活。

這可能是值得一讀一些關於演員的生命週期https://azure.microsoft.com/en-gb/documentation/articles/service-fabric-reliable-actors-lifecycle/

+0

我已經刪除了對OnActivateAsync的調用,而是從Get和Add方法中使用StateManager.GetOrAddStateAsync。奇怪的是,這種行爲依然存在。 – Landrew

+0

你是否解決了這個問題?如果沒有,可能值得發佈您的更新代碼。 – charisk

+0

未解決,但我更新了代碼以反映我的最後一次嘗試。 – Landrew

1

怎麼樣,而不是使用OnActivate()方法需要初始化你的狀態,你在你的AddTextAsync(string text)方法來初始化呢?

public async Task AddTextAsync(string text) 
{ 
    // Try and get the state 
    var conditionalTexts = await this.StateManager.TryGetStateAsync<List<string>>("State"); 
    // If it exists, use it, otherwise create a new one 
    List<string> texts = conditionalTexts.HasValue ? conditionalTexts.Value : new List<string>(); 
    // Make your changes 
    texts.Add(text); 
    // Save the state 
    await this.StateManager.SetStateAsync("State", texts); 
} 
+0

這是我測試過的許多變體之一,所有變體仍然具有相同的結果。短短一段時間後,文字消失了。 – Landrew

+0

你正在使用某個自定義類的'string'或'List <>'的'List <>?如果它是一個類,那麼您是否已經使用所需的[DataContract]和[DataMember]屬性進行設置? –