Service Fabric, определите, существует ли конкретный субъект - PullRequest
0 голосов
/ 31 октября 2018

Мы используем Azure Service Fabric и используем актеров для моделирования конкретных устройств, используя идентификатор устройства в качестве ActorId. Service Fabric создаст экземпляр нового экземпляра субъекта, когда мы запросим субъекта для данного идентификатора, если он еще не создан, но я не могу найти API, который позволяет мне запрашивать, есть ли у конкретного идентификатора устройства уже созданный субъект.

Я понимаю, что могут быть некоторые распределенные / временные проблемы при получении истины на определенный момент времени, но для нашей конкретной цели нам не нужен трудный ответ в реальном времени на это, но мы можем согласиться с лучшим предположением. Мы просто хотели бы, теоретически, связаться с текущим первичным сервером для конкретного раздела, разрешенного ActorId, и узнать, есть ли на устройстве экземпляр созданного субъекта.

В идеале это быстрый / производительный вызов, существенно более быстрый, чем, например, создание экземпляра субъекта и вызов метода, чтобы понять, правильно ли он инициализирован и не является ли он «пустым» субъектом.

Вы можете использовать ActorServiceProxy для перебора информации для конкретного раздела, но это не очень эффективный способ получения информации.

Кто-нибудь с пониманием этого?

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

В качестве альтернативы, вы можете создать состояние DeviceActorStatusActor, которое будет уведомлено (вызвано) DeviceActor, как только оно будет создано. (Разделите ActorId для корреляции.)

В зависимости от ваших потребностей вы также можете зарегистрировать несколько актеров с одним и тем же актером отслеживания статуса.

У вас будет отличная производительность и информация почти в реальном времени.

0 голосов
/ 31 октября 2018

Единственный официальный способ проверить, был ли актер активирован в каком-либо Сервисном разделе ранее, - это запрос ActorServiceProxy, как описано здесь :

IActorService actorServiceProxy = ActorServiceProxy.Create(
    new Uri("fabric:/MyApp/MyService"), partitionKey);

ContinuationToken continuationToken = null;
do
{
    PagedResult<ActorInformation> page = await actorServiceProxy.GetActorsAsync(continuationToken, cancellationToken);

    var actor = page.Items.FirstOrDefault(x => x.ActorId == idToFind);

    continuationToken = page.ContinuationToken;
}
while (continuationToken != null);

По своей природе актеры SF являются виртуальными, что означает, что они всегда существуют, даже если вы не активировали ранее, поэтому сделать эту проверку немного сложнее.

Как вы сказали, опрашивать всех актеров нецелесообразно, поэтому вы можете попробовать и другие обходные пути:

  1. Храните идентификаторы в надежном словаре в другом месте, каждый раз, когда активируется актер, вы инициируете событие и вставляете идентификаторы ActorID в словарь, если его еще нет.

    • Вы можете использовать OnActivateAsync() событие актера, чтобы уведомить о его создании, или
    • Вы можете использовать пользовательскую фабрику акторов в ActorService для регистрации активации актера
    • Вы можете сохранить словарь в другом актере или другом StatefulService
  2. Создать в акторе свойство, которое устанавливается самим актером при его активации.

    • OnActivateAsync() проверяет, было ли установлено это свойство до
    • Если еще не установлено, вы устанавливаете новое значение и сохраняете в переменной (непостоянное значение), чтобы сказать, что актер новый
    • Всякий раз, когда вы взаимодействуете с актером, вы устанавливаете это, чтобы указать, что он больше не нов.
    • При следующей активации свойство уже будет установлено, и ничего не должно происходить.
  3. Создайте собственный IActorStateProvider, чтобы сделать то же самое, что упомянуто в варианте 2, вместо того, чтобы обрабатывать его в актере, он будет обрабатывать уровень под ним. Честно говоря, я думаю, что это немного поработало, было бы удобно, если бы вы делали то же самое для многих типов актеров, варианты 1 и 2 были бы намного проще.

  4. Делать как Питер Бонс Рекомендуется, хранить ActorID вне ActorService, как в БД, Я бы предложил этот вариант, только если вы должны проверить это снаружи кластера .

.

Следующие фрагменты могут помочь вам, если вы хотите управлять этими событиями вне субъекта.

private static void Main()
{
    try
    {
        ActorRuntime.RegisterActorAsync<NetCoreActorService>(
           (context, actorType) => new ActorService(context, actorType,
                    new Func<ActorService, ActorId, ActorBase>((actorService, actorId) =>
                    {
                        RegisterActor(actorId);//The custom method to register the actor if new
                        return (ActorBase)Activator.CreateInstance(actorType.ImplementationType, actorService, actorId);
                    })
                )).GetAwaiter().GetResult();

        Thread.Sleep(Timeout.Infinite);
    }
    catch (Exception e)
    {
        ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
        throw;
    }
}

private static void RegisterActor(ActorId actorId) 
{
    //Here you will put the logic to register elsewhere the actor creation
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...