为什么演员状态会丢失?
Why is actor state lost?
我正在 Azure Service Fabric 中创建参与者服务。当部署到 Azure 时,一开始它似乎可以正常工作。可以添加和 return 编辑文本(演员前面有一个 Web API),但闲置一段时间后,GetTextsAsync return 变成一个空集合。
编辑:
我已经更新了代码,在添加之前检查状态是否存在,但并没有解决问题。
[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:
好像演员本身被替换了一样。我将演员修改为 return 其 ActorId,当文本列表消失时,ActorId 也被替换为新的。
我遵循 VoiceMailBox 示例中的模式,其中的参与者是在控制器中静态创建的。是这个问题吗?
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
}
这是因为您在 OnActivate()
方法中的代码 - 它将状态重置为新列表。
OnActivate()
方法可以在一个 actor 上多次调用 - 它不仅在您第一次创建特定 actor 时被调用。如果 actor 一段时间未使用,则它会被停用(并调用 OnDeactivateAsync()
方法)。但是当对actor进行新的调用时,它又被激活了。
关于 actor 生命周期可能值得一读 https://azure.microsoft.com/en-gb/documentation/articles/service-fabric-reliable-actors-lifecycle/
如果不使用 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);
}
我正在 Azure Service Fabric 中创建参与者服务。当部署到 Azure 时,一开始它似乎可以正常工作。可以添加和 return 编辑文本(演员前面有一个 Web API),但闲置一段时间后,GetTextsAsync return 变成一个空集合。
编辑: 我已经更新了代码,在添加之前检查状态是否存在,但并没有解决问题。
[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: 好像演员本身被替换了一样。我将演员修改为 return 其 ActorId,当文本列表消失时,ActorId 也被替换为新的。
我遵循 VoiceMailBox 示例中的模式,其中的参与者是在控制器中静态创建的。是这个问题吗?
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
}
这是因为您在 OnActivate()
方法中的代码 - 它将状态重置为新列表。
OnActivate()
方法可以在一个 actor 上多次调用 - 它不仅在您第一次创建特定 actor 时被调用。如果 actor 一段时间未使用,则它会被停用(并调用 OnDeactivateAsync()
方法)。但是当对actor进行新的调用时,它又被激活了。
关于 actor 生命周期可能值得一读 https://azure.microsoft.com/en-gb/documentation/articles/service-fabric-reliable-actors-lifecycle/
如果不使用 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);
}