Időzítők és emlékeztetők
A Orleans futtatókörnyezet két mechanizmust, úgynevezett időzítőket és emlékeztetőket biztosít, amelyek lehetővé teszik a fejlesztő számára a szemcsék rendszeres viselkedésének megadását.
Időzítők
Az időzítők olyan rendszeres szemcse viselkedést hoznak létre, amely nem szükséges több aktiválás (a szem példányainak) lefedéséhez. Az időzítő megegyezik a standard .NET-osztálysal System.Threading.Timer . Ezen kívül az időzítőkre egyszálas végrehajtási garanciák vonatkoznak az általuk működtetett gabona aktiválásán belül, és a végrehajtásuk más kérésekkel van összekötve, mintha az időzítő visszahívása egy szemcsés metódus volt megjelölve AlwaysInterleaveAttribute.
Minden aktiváláshoz nulla vagy több időzítő lehet társítva. A futtatókörnyezet minden időzítő rutint végrehajt az aktiválás futásidejű környezetében, amelyhez társítva van.
Időzítő használata
Időzítő indításához használja a Grain.RegisterTimer metódust, amely egy IDisposable hivatkozást ad vissza:
protected IDisposable RegisterTimer(
Func<object, Task> asyncCallback, // function invoked when the timer ticks
object state, // object to pass to asyncCallback
TimeSpan dueTime, // time to wait before the first timer tick
TimeSpan period) // the period of the timer
Az időzítő megszakításához törölje azt.
Az időzítő nem aktiválódik, ha a szemcse inaktiválva van, vagy ha hiba történik, és a siló összeomlik.
Fontos szempontok:
- Ha az aktiválási gyűjtemény engedélyezve van, az időzítő visszahívásának végrehajtása nem módosítja az aktiválás állapotát tétlenségről használaton kívülire. Ez azt jelenti, hogy az időzítő nem használható az egyébként tétlen aktiválások inaktiválásának elhalasztására.
- Az átadott
Grain.RegisterTimer
időszak az az időtartam, amely a feladat visszaadásánakasyncCallback
pillanatától a következő meghívásasyncCallback
időpontjáig tart. Ez nem csak lehetetlenné teszi az egymást követő hívásokasyncCallback
átfedését, hanem azt is, hogy a teljes időtartamasyncCallback
befolyásolja a meghívás gyakoriságátasyncCallback
. Ez egy fontos eltérés a szemantikától System.Threading.Timer. - Az egyes meghívások
asyncCallback
külön fordulóban érkeznek az aktiváláshoz, és soha nem futnak egyidejűleg ugyanazon aktiválás más bekapcsolásaival. AzasyncCallback
invokációk azonban nem üzenetekként érkeznek, ezért nem vonatkoznak az üzenetek közötti szemantikára. Ez azt jelenti, hogy az invokációkasyncCallback
úgy viselkednek, mintha a gabona újra beléptethető volna, és más szemcsekérésekkel egyidejűleg hajtanak végre. A gabona kérésütemezési szemantikájának használatához meghívhat egy gabonametódust a benneasyncCallback
elvégzett munka végrehajtásához. Egy másik alternatíva egyAsyncLock
vagy egy SemaphoreSlim. Részletesebb magyarázat a GitHub 2574-ik számában Orleans érhető el.
Emlékeztetők
Az emlékeztetők hasonlóak az időzítőkhöz, néhány fontos különbséggel:
- Az emlékeztetők állandóak, és szinte minden esetben aktiválódnak (beleértve a részleges vagy teljes fürt újraindítását is), kivéve, ha explicit módon lemondják.
- Az emlékeztető "definíciói" a tárolóba vannak írva. Az egyes előfordulások azonban nem az adott időponttal együtt. Ennek az a mellékhatása, hogy ha a fürt egy adott emlékeztetőjel időpontjában nem működik, akkor a rendszer kihagyja, és csak az emlékeztető következő osztásjele történik meg.
- Az emlékeztetők egy szemcséhez vannak társítva, nem egy adott aktiváláshoz.
- Ha egy szemcse nem rendelkezik aktiválással, amikor egy emlékeztető ketyeg, a szemcse létrejön. Ha egy aktiválás tétlenné válik, és inaktiválva van, az ugyanahhoz a szemhez társított emlékeztető újraaktiválja a szemcsét, amikor a következő ketyeg.
- Az emlékeztető kézbesítése üzenetben történik, és ugyanolyan összefüggő szemantikára vonatkozik, mint az összes többi szemantika.
- Az emlékeztetőket nem szabad nagy gyakoriságú időzítőkhöz használni, az időtartamukat percekben, órákban vagy napokban kell mérni.
Konfiguráció
Az emlékeztetők állandóak, és a tárolásra támaszkodnak a működéshez.
Meg kell adnia, hogy az emlékeztető alrendszer működése előtt melyik tárterület-háttérrendszert kell használnia.
Ez az emlékeztetőszolgáltatók egyikének bővítménymetelyekkel Use{X}ReminderService
történő konfigurálásával történik, ahol X
például UseAzureTableReminderServicea szolgáltató neve szerepel.
Azure Table-konfiguráció:
// TODO replace with your connection string
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseAzureTableReminderService(connectionString)
})
.Build();
SQL:
const string connectionString = "YOUR_CONNECTION_STRING_HERE";
const string invariant = "YOUR_INVARIANT";
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseAdoNetReminderService(options =>
{
options.ConnectionString = connectionString; // Redacted
options.Invariant = invariant;
});
})
.Build();
Ha csak azt szeretné, hogy az emlékeztetők helyőrző implementációja úgy működjön, hogy nincs szükség Azure-fiók vagy SQL-adatbázis beállítására, akkor ez az emlékeztetőrendszer csak fejlesztési célú implementációját biztosítja:
var silo = new HostBuilder()
.UseOrleans(builder =>
{
builder.UseInMemoryReminderService();
})
.Build();
Emlékeztetők használata
Az emlékeztetőket használó szemcséknek implementálniuk kell a metódust IRemindable.ReceiveReminder .
Task IRemindable.ReceiveReminder(string reminderName, TickStatus status)
{
Console.WriteLine("Thanks for reminding me-- I almost forgot!");
return Task.CompletedTask;
}
Emlékeztető indításához használja a Grain.RegisterOrUpdateReminder metódust, amely egy objektumot IGrainReminder ad vissza:
protected Task<IGrainReminder> RegisterOrUpdateReminder(
string reminderName,
TimeSpan dueTime,
TimeSpan period)
reminderName
: olyan sztring, amely egyedileg azonosítja az emlékeztetőt a környezetfüggő szemcse hatókörén belül.dueTime
: megadja, hogy mennyi ideig kell várni az első időzítőjel kiadása előtt.period
: az időzítő időtartamát adja meg.
Mivel az emlékeztetők túlélik az egyetlen aktiválás élettartamát, explicit módon le kell mondani őket (a törlés helyett). Az emlékeztetőt a következő hívással Grain.UnregisterReminderszakíthatja meg:
protected Task UnregisterReminder(IGrainReminder reminder)
Ez reminder
az a leíróobjektum, amelyet Grain.RegisterOrUpdateRemindera függvény visszaadott.
A példányok IGrainReminder
nem garantáltan érvényesek az aktiválás élettartamán túl. Ha egy emlékeztetőt olyan módon szeretne azonosítani, amely megmarad, használjon egy sztringet, amely az emlékeztető nevét tartalmazza.
Ha csak az emlékeztető nevét használja, és a megfelelő példányra IGrainReminder
van szüksége, hívja meg a metódust Grain.GetReminder :
protected Task<IGrainReminder> GetReminder(string reminderName)
Döntse el, hogy melyiket használja
Javasoljuk, hogy az alábbi esetekben használjon időzítőket:
- Ha nem számít (vagy kívánatos), hogy az időzítő az aktiválás inaktiválásakor vagy meghibásodása esetén megszűnik.
- Az időzítő felbontása kicsi (például másodpercben vagy percben kifejezhető).
- Az időzítő visszahívása elindítható egy gabonametódus meghívásával Grain.OnActivateAsync() vagy meghívásával.
Javasoljuk, hogy az alábbi esetekben használjon emlékeztetőket:
- Ha az időszakos viselkedésnek túl kell élnie az aktiválást és az esetleges hibákat.
- Ritkán (például percekben, órákban vagy napokban kifejezhető) feladatok végrehajtása.
Időzítők és emlékeztetők egyesítése
Érdemes lehet emlékeztetők és időzítők kombinációját használni a cél eléréséhez. Ha például egy kis felbontású időzítőre van szüksége, amelynek az aktiválások során túl kell maradnia, használhat egy öt percenként futó emlékeztetőt, amelynek célja egy olyan szemcse felébresztése, amely újraindít egy helyi időzítőt, amely az inaktiválás miatt elveszett lehet.
POCO-gabonaregisztrációk
Ha időzítőt vagy emlékeztetőt szeretne regisztrálni egy POCO-szemcsével, implementálja az IGrainBase interfészt, és injektálja a ITimerRegistry szemcse konstruktorába vagy IReminderRegistry annak konstruktorába.
using Orleans.Runtime;
using Orleans.Timers;
namespace Timers;
public sealed class PingGrain : IGrainBase, IPingGrain, IDisposable
{
private const string ReminderName = "ExampleReminder";
private readonly IReminderRegistry _reminderRegistry;
private IGrainReminder? _reminder;
public IGrainContext GrainContext { get; }
public PingGrain(
ITimerRegistry timerRegistry,
IReminderRegistry reminderRegistry,
IGrainContext grainContext)
{
// Register timer
timerRegistry.RegisterTimer(
grainContext,
asyncCallback: static async state =>
{
// Omitted for brevity...
// Use state
await Task.CompletedTask;
},
state: this,
dueTime: TimeSpan.FromSeconds(3),
period: TimeSpan.FromSeconds(10));
_reminderRegistry = reminderRegistry;
GrainContext = grainContext;
}
public async Task Ping()
{
_reminder = await _reminderRegistry.RegisterOrUpdateReminder(
callingGrainId: GrainContext.GrainId,
reminderName: ReminderName,
dueTime: TimeSpan.Zero,
period: TimeSpan.FromHours(1));
}
void IDisposable.Dispose()
{
if (_reminder is not null)
{
_reminderRegistry.UnregisterReminder(
GrainContext.GrainId, _reminder);
}
}
}
A fenti kód a következőket végzi el:
- Meghatároz egy POCO-szemcsét, amely implementálja IGrainBaseaz ,
IPingGrain
és IDisposable. - Regisztrál egy 10 másodpercenként meghívott időzítőt, és 3 másodperccel a regisztráció után indul el.
- Amikor
Ping
meghívják, egy óránként meghívott emlékeztetőt regisztrál, és a regisztrációt követően azonnal elindul. - A
Dispose
metódus törli az emlékeztetőt, ha regisztrálva van.
Visszajelzés
https://aka.ms/ContentUserFeedback.
Hamarosan elérhető: 2024-ben fokozatosan kivezetjük a GitHub-problémákat a tartalom visszajelzési mechanizmusaként, és lecseréljük egy új visszajelzési rendszerre. További információ:Visszajelzés küldése és megtekintése a következőhöz: