Share via


Aktor időzítői és emlékeztetői

Az aktorok rendszeres munkát ütemezhetnek magukra időzítők vagy emlékeztetők regisztrálásával. Ez a cikk bemutatja, hogyan használhat időzítőket és emlékeztetőket, és ismerteti a köztük lévő különbségeket.

Aktor időzítői

Az aktor-időzítők egyszerű burkolót biztosítanak egy .NET- vagy Java-időzítő körül, hogy a visszahívási metódusok betarthassák az Actors-futtatókörnyezet által biztosított turn-alapú egyidejűséget.

Az aktorok a (C#) vagy registerTimer(RegisterTimerJava) és (C#) vagy UnregisterTimerunregisterTimer(Java) metódusokat használhatják az alaposztályukon az időzítők regisztrálásához és regisztrációjának törléséhez. Az alábbi példa az időzítő API-k használatát mutatja be. Az API-k nagyon hasonlóak a .NET-időzítőhöz vagy a Java-időzítőhöz. Ebben a példában, ha az időzítő esedékes, az Actors-futtatókörnyezet meghívja a (C#) vagy moveObjecta MoveObject(Java) metódust. A metódus garantáltan tiszteletben tartja a fordulóalapú egyidejűséget. Ez azt jelenti, hogy a visszahívás végrehajtásáig nem lesznek folyamatban más aktor metódusok vagy időzítő/emlékeztető visszahívások.

class VisualObjectActor : Actor, IVisualObject
{
    private IActorTimer _updateTimer;

    public VisualObjectActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    protected override Task OnActivateAsync()
    {
        ...

        _updateTimer = RegisterTimer(
            MoveObject,                     // Callback method
            null,                           // Parameter to pass to the callback method
            TimeSpan.FromMilliseconds(15),  // Amount of time to delay before the callback is invoked
            TimeSpan.FromMilliseconds(15)); // Time interval between invocations of the callback method

        return base.OnActivateAsync();
    }

    protected override Task OnDeactivateAsync()
    {
        if (_updateTimer != null)
        {
            UnregisterTimer(_updateTimer);
        }

        return base.OnDeactivateAsync();
    }

    private Task MoveObject(object state)
    {
        ...
        return Task.FromResult(true);
    }
}
public class VisualObjectActorImpl extends FabricActor implements VisualObjectActor
{
    private ActorTimer updateTimer;

    public VisualObjectActorImpl(FabricActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    @Override
    protected CompletableFuture onActivateAsync()
    {
        ...

        return this.stateManager()
                .getOrAddStateAsync(
                        stateName,
                        VisualObject.createRandom(
                                this.getId().toString(),
                                new Random(this.getId().toString().hashCode())))
                .thenApply((r) -> {
                    this.registerTimer(
                            (o) -> this.moveObject(o),                        // Callback method
                            "moveObject",
                            null,                                             // Parameter to pass to the callback method
                            Duration.ofMillis(10),                            // Amount of time to delay before the callback is invoked
                            Duration.ofMillis(timerIntervalInMilliSeconds));  // Time interval between invocations of the callback method
                    return null;
                });
    }

    @Override
    protected CompletableFuture onDeactivateAsync()
    {
        if (updateTimer != null)
        {
            unregisterTimer(updateTimer);
        }

        return super.onDeactivateAsync();
    }

    private CompletableFuture moveObject(Object state)
    {
        ...
        return this.stateManager().getStateAsync(this.stateName).thenCompose(v -> {
            VisualObject v1 = (VisualObject)v;
            v1.move();
            return (CompletableFuture<?>)this.stateManager().setStateAsync(stateName, v1).
                    thenApply(r -> {
                      ...
                      return null;});
        });
    }
}

Az időzítő következő időszaka a visszahívás végrehajtása után kezdődik. Ez azt jelenti, hogy az időzítő le van állítva a visszahívás végrehajtása közben, és a visszahívás befejezésekor indul el.

Az Actors-futtatókörnyezet menti az aktor Állapotkezelőjének módosításait, amikor a visszahívás befejeződik. Ha hiba történik az állapot mentésekor, a rendszer inaktiválja az aktorobjektumot, és aktivál egy új példányt.

Az emlékeztetőktől eltérően az időzítők nem frissíthetők. Ha RegisterTimer a rendszer ismét meghívja, egy új időzítő lesz regisztrálva.

Minden időzítő le lesz állítva, ha az aktort a szemétgyűjtés részeként inaktiválja. Ezután a rendszer nem hív meg időzítővisszahívásokat. Emellett az Actors-futtatókörnyezet nem őriz meg semmilyen információt az inaktiválás előtt futó időzítőkről. Az aktoron múlik, hogy regisztrálja-e azokat az időzítőket, amelyekre szüksége van, amikor a jövőben újraaktiválják. További információkért lásd az aktor szemétgyűjtéséről szóló szakaszt.

Aktoremlékek

Az emlékeztetők olyan mechanizmusok, amelyek állandó visszahívásokat aktiválnak egy aktoron a megadott időpontokban. A funkciójuk hasonló az időzítőkhöz. Az időzítőkkel ellentétben azonban az emlékeztetők minden körülmények között aktiválódnak, amíg az aktor explicit módon nem törli a regisztrációt, vagy az aktor explicit módon törlődik. Az emlékeztetők az aktor-deaktivációk és feladatátvételek során aktiválódnak, mivel az Actors-futtatókörnyezet az aktor állapotszolgáltatójának használatával megőrzi az aktor emlékeztetőivel kapcsolatos információkat. Az időzítőktől eltérően a meglévő emlékeztetők is frissíthetők a regisztrációs módszer (RegisterReminderAsync) ismételt meghívásával ugyanazzal a reminderName névvel.

Megjegyzés

Az emlékeztetők megbízhatósága az aktor állapotszolgáltatója által biztosított állapot-megbízhatósági garanciákhoz van kötve. Ez azt jelenti, hogy azoknak a szereplőknek, akiknek az állapotmegőrzése Nincs értékre van állítva, az emlékeztetők nem indulnak el feladatátvétel után.

Emlékeztető regisztrálásához az aktor meghívja az RegisterReminderAsync alaposztályban megadott metódust az alábbi példában látható módon:

protected override async Task OnActivateAsync()
{
    string reminderName = "Pay cell phone bill";
    int amountInDollars = 100;

    IActorReminder reminderRegistration = await this.RegisterReminderAsync(
        reminderName,
        BitConverter.GetBytes(amountInDollars),
        TimeSpan.FromDays(3),    //The amount of time to delay before firing the reminder
        TimeSpan.FromDays(1));    //The time interval between firing of reminders
}
@Override
protected CompletableFuture onActivateAsync()
{
    String reminderName = "Pay cell phone bill";
    int amountInDollars = 100;

    ActorReminder reminderRegistration = this.registerReminderAsync(
            reminderName,
            state,
            dueTime,    //The amount of time to delay before firing the reminder
            period);    //The time interval between firing of reminders
}

Ebben a példában "Pay cell phone bill" az emlékeztető neve. Ez egy olyan sztring, amellyel az aktor egyedileg azonosítja az emlékeztetőket. BitConverter.GetBytes(amountInDollars)A (C#) az emlékeztetőhöz társított környezet. A rendszer az emlékeztető visszahívás argumentumaként adja vissza az aktornak, azaz IRemindable.ReceiveReminderAsync(C#) vagy Remindable.receiveReminderAsync(Java).

Az emlékeztetőket használó szereplőknek implementálniuk kell a IRemindable felületet az alábbi példában látható módon.

public class ToDoListActor : Actor, IToDoListActor, IRemindable
{
    public ToDoListActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId)
    {
    }

    public Task ReceiveReminderAsync(string reminderName, byte[] context, TimeSpan dueTime, TimeSpan period)
    {
        if (reminderName.Equals("Pay cell phone bill"))
        {
            int amountToPay = BitConverter.ToInt32(context, 0);
            System.Console.WriteLine("Please pay your cell phone bill of ${0}!", amountToPay);
        }
        return Task.FromResult(true);
    }
}
public class ToDoListActorImpl extends FabricActor implements ToDoListActor, Remindable
{
    public ToDoListActor(FabricActorService actorService, ActorId actorId)
    {
        super(actorService, actorId);
    }

    public CompletableFuture receiveReminderAsync(String reminderName, byte[] context, Duration dueTime, Duration period)
    {
        if (reminderName.equals("Pay cell phone bill"))
        {
            int amountToPay = ByteBuffer.wrap(context).getInt();
            System.out.println("Please pay your cell phone bill of " + amountToPay);
        }
        return CompletableFuture.completedFuture(true);
    }

Emlékeztető aktiválásakor a Reliable Actors futtatókörnyezet meghívja a ReceiveReminderAsync(C#) vagy receiveReminderAsync(Java) metódust az Aktoron. Az aktorok több emlékeztetőt is regisztrálhatnak, és a ReceiveReminderAsync(C#) vagy receiveReminderAsynca (Java) metódus akkor lesz meghívva, ha ezek bármelyike aktiválódik. Az aktor a (C#) vagy receiveReminderAsynca (Java) metódusnak ReceiveReminderAsyncátadott emlékeztetőnévvel állapíthatja meg, hogy melyik emlékeztető aktiválódott.

Az Actors-futtatókörnyezet menti az aktor állapotát, amikor a ReceiveReminderAsync(C#) vagy receiveReminderAsynca (Java) hívás befejeződik. Ha hiba történik az állapot mentésekor, a rendszer inaktiválja az aktorobjektumot, és aktivál egy új példányt.

Az emlékeztető regisztrációjának törléséhez az aktor meghívja a UnregisterReminderAsync(C#) vagy unregisterReminderAsynca (Java) metódust az alábbi példákban látható módon.

IActorReminder reminder = GetReminder("Pay cell phone bill");
Task reminderUnregistration = await UnregisterReminderAsync(reminder);
ActorReminder reminder = getReminder("Pay cell phone bill");
CompletableFuture reminderUnregistration = unregisterReminderAsync(reminder);

Ahogy fent látható, a UnregisterReminderAsync(C#) vagy unregisterReminderAsynca (Java) metódus (C#) vagy ActorReminder(Java) felületet fogad elIActorReminder. Az aktor alaposztálya támogatja a GetReminder(C#) vagy getRemindera (Java) metódust, amely a IActorReminder(C#) vagy ActorRemindera (Java) felület lekéréséhez használható az emlékeztető nevének megadásával. Ez kényelmes, mert az aktornak nem kell megőriznie a IActorReminder(C#) vagy (Java) metódushívásból RegisterRemindervisszaadott (C#) vagy ActorReminderregisterReminder(Java) felületet.

Következő lépések

További információ a Reliable Actor-eseményekről és az újrarendezésről: