在 {time} 后为参与者“{actorName}”获取基于回合的并发锁超时

Acquisition of turn based concurrency lock for actor '{actorName}' timed out after {time}

我有通过某个名称创建某种类型的 Actor 的服务:

var storer = this.serviceClient.Create<IStorer>(new ActorId(agencyToProcess.Name));

然后调用Actor的方法

await storer.StoreStatusesAsync().ConfigureAwait(false);

在这个调用中我收到错误:

System.AggregateException: One or more errors occurred. ---> Microsoft.ServiceFabric.Actors.ActorConcurrencyLockTimeoutException: Acquisition of turn based concurrency lock for actor 'actorName' timed out after 00:01:13.6480000. at Microsoft.ServiceFabric.Actors.Runtime.ActorConcurrencyLock.d__17.MoveNext()

我不明白这个错误是什么意思以及如何解决它。

这个问题不是每次都会发生。 (100 次中有 20 次)。


[ServiceDescription("Storer", ServicePrefix = "MyApp")]
public interface IStorer : IActor
{
    Task StoreStatusesAsync();
}

此服务是在 Observer 中创建的。有在观察者中创建演员的完整代码。

public async void OnNext(AgencyModel agencyToProcess)
{
    try
    {
        var storer = this.serviceClient.Create<IStorer>(new ActorId(agencyToProcess.Name));

        await storer.StoreStatusesAsync().ConfigureAwait(false);
    }
    catch (Exception exception)
    {
        this.Logger.Error(exception);
    }
}

发生这种情况是因为您的服务正在尝试调用当前锁定处理另一个调用的 Actor。

从你的代码来看,你是基于事件触发actor,如果连续调用针对同一个actor的两个事件,其中一个会等待前一个完成,如果前一个花费的时间太长完成,超时将抛出 'ActorConcurrencyLockTimeoutException'.

这种情况不会经常发生,因为每个调用可能需要几秒钟或更短的时间来处理,但是当您有很多调用排队时,最新的将等待所有前面的调用按各自的顺序处理,这很快就会超时或更高版本。

要减少这些异常,您可以增加超时阈值,默认值为 60 秒,但我认为这不是一个好主意,因为它可能会使太多请求排队并且可能无法处理所有请求,同时持有资源和连接。当服务重新平衡时,这些请求也可能丢失。

最好的解决方案是找到一种方法来限制这些请求。