Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az entitásfüggvények olyan műveleteket határoznak meg, amelyek kis méretű állapotokat, úgynevezett tartós entitásokat olvasnak és frissítenek. A vezénylőfüggvényekhez hasonlóan az entitásfüggvények is egy speciális eseményindító-típust, az entitás-eseményindítót használják. A vezénylőfüggvényekkel ellentétben az entitásfüggvények explicit módon kezelik az entitásállapotokat ahelyett, hogy az állapotot a vezérlőfolyamaton keresztül jelölik. Az entitások segítenek az alkalmazások vertikális felskálázásában azáltal, hogy a munkát számos entitás között osztja el, amelyek mindegyike szerény állapotú.
Az entitások olyan műveleteket határoznak meg, amelyek kis méretű állapotokat, úgynevezett tartós entitásokat olvasnak és frissítenek. A vezénylőkkel ellentétben az entitások explicit módon kezelik az állapotot ahelyett, hogy az állapotot a vezérlési folyamaton keresztül jelölik. Az entitások segítenek az alkalmazások vertikális felskálázásában azáltal, hogy a munkát számos entitás között osztja el, amelyek mindegyike szerény állapotú.
Tartós entitások támogatása
Az entitásfüggvények és a kapcsolódó funkciók Durable Functions 2.0 és újabb verziókban érhetők el.
| Programozási nyelv | Tartós entitások támogatása |
|---|---|
| .NET független | ✅ |
| .NET folyamatban | ✅ |
| Java | ✅ |
| Python | ✅ |
| JavaScript | ✅ |
| PowerShell | ❌ |
| Tartós feladat SDK | Tartós entitások támogatása |
|---|---|
| .NET független | ✅ |
| .NET folyamatban | ✅ |
| Java | ✅ |
| Python | ✅ |
| JavaScript | ✅ |
| PowerShell | ❌ |
A tartós entitások általános fogalmai
Az entitások az üzenetek használatával kommunikáló kis szolgáltatásokhoz hasonlóan működnek. Minden entitás egyedi identitással és szükség esetén belső állapotú. Az entitások akkor futtatják a műveleteket, amikor a rendszer kéri. Előfordulhat, hogy egy művelet frissíti az állapotot, meghívja a külső szolgáltatásokat, vagy megvárja a választ. Az entitások a futtatókörnyezet által megbízható üzenetsorokon keresztül küldött üzeneteken keresztül kommunikálnak más entitásokkal, vezénylésekkel és ügyfelekkel.
Az ütközések elkerülése érdekében egyetlen entitás egymás után futtatja a műveleteket egymás után.
Megjegyzés:
Amikor meghív egy entitást, az feldolgozza a hasznos adatokat a befejezésig, majd ütemez egy új végrehajtást, amely új bemenet érkezésekor aktiválódik. Ennek eredményeképpen előfordulhat, hogy az entitás-végrehajtási naplók minden egyes meghívás után további végrehajtást mutatnak. Ez várható.
Entitás azonosítója
Az entitás azonosítójával érhet el egy entitást. Az entitásazonosító egy sztringpár, amely egyedileg azonosít egy entitáspéldányt. A következőkből áll:
-
Entitás neve, amely azonosítja az entitás típusát. Például:
Counter. Ez a név megegyezik az entitást megvalósító entitásfüggvény nevével. A kis- és nagybetűk nem érzékenyek. - Entitáskulcs, amely egyedileg azonosítja az entitást az azonos nevű többi entitás között. Például egy GUID.
Például egy Counter entitásfüggvény használható a pontszám online játékban való megtartásához. A játék minden példánya egyedi entitásazonosítóval rendelkezik, például @Counter@Game1 és @Counter@Game2. Egy entitás megcélzásához adja meg az entitás azonosítóját.
Entitásműveletek
Egy entitáson végzett művelet meghívásához adja meg a következőket:
- A cél entitás entitásazonosítója.
-
Művelet neve, amely egy sztring, amely meghatározza a végrehajtandó műveletet. Például az
Counterentitás támogathatja aadd,get, vagyresetműveleteket. -
Művelet bemenete, amely a művelet opcionális paramétere. A művelet például
addegy egész számot vesz fel bemenetként. - Ütemezett idő, amely nem kötelező paraméter a művelet kézbesítési idejének megadásához. Ütemezzen például egy műveletet néhány nappal későbbre.
A műveletek eredményértéket vagy hibaeredményt, például JavaScript-hibát vagy .NET kivételt adhatnak vissza. A hívó orkesztráció megkapja az eredményt vagy a hibát.
A műveletek eredményértéket vagy hibaeredményt adhatnak vissza, például .NET kivételt vagy Python kivételt. A hívó megkapja az eredményt vagy a hibát.
Az entitásművelet emellett létrehozhatja, elolvashatja, frissítheti és törölheti az entitás állapotát. A futtatókörnyezet mindig megőrzi az entitás állapotát a tárolóban.
Entitások definiálása
Két API egyikével definiálhat entitásokat a .NET:
Függvényalapú szintaxis: A függvényalapú szintaxisban minden entitást függvényként kell írnia, és műveleteket kell küldenie az alkalmazásban. Ez a szintaxis jól működik az egyszerű állapotú, kevés művelettel vagy dinamikus műveletkészlettel rendelkező entitások esetében, például az alkalmazás-keretrendszerekben. A karbantartás azonban nehézkes lehet, mert fordításkor nem észlel típushibákat.
Osztályalapú szintaxis: Az osztályalapú szintaxisban .NET osztályok és metódusok entitásai és műveletei. Ez a szintaxis megkönnyíti a kód olvasását, és lehetővé teszi a műveletek biztonságos típusba hívását. Ez egy vékony réteg a függvényalapú szintaxis tetején, így mindkét változatot kombinálhatja ugyanabban az alkalmazásban.
A használt API-k attól függenek, hogy hol futnak a C# függvények. Ajánlott izolált feldolgozói folyamat , de futtatható a gazdafolyamatban is.
Folyamaton belüli függvényalapú példa:
Ez a példa egy egyszerű entitást Counter mutat be, amely tartós függvényként van implementálva. Három olyan műveletet határoz meg,addresetget amelyek egész számot használnak.
[FunctionName("Counter")]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
switch (ctx.OperationName.ToLowerInvariant())
{
case "add":
ctx.SetState(ctx.GetState<int>() + ctx.GetInput<int>());
break;
case "reset":
ctx.SetState(0);
break;
case "get":
ctx.Return(ctx.GetState<int>());
break;
}
}
További információ: Függvényalapú szintaxis.
Folyamatközi osztályalapú példa:
Ez a példa ugyanazt Counter az entitást mutatja be, amelyet osztályok és metódusok használatával valósítottak meg.
[JsonObject(MemberSerialization.OptIn)]
public class Counter
{
[JsonProperty("value")]
public int CurrentValue { get; set; }
public void Add(int amount) => this.CurrentValue += amount;
public void Reset() => this.CurrentValue = 0;
public int Get() => this.CurrentValue;
[FunctionName(nameof(Counter))]
public static Task Run([EntityTrigger] IDurableEntityContext ctx)
=> ctx.DispatchAsync<Counter>();
}
Ez az entitás az Counter aktuális számláló értékét tartalmazó objektumban tárolja az állapotot. Durable Functions szerializálja és deszerializálja ezt az objektumot a Json.NET könyvtár használatával.
További információ: Entitásosztályok definiálása.
Izolált feldolgozási folyamatfüggvény alapú példa:
Az alábbi példa egy függvényalapú Counter entitást mutat be egy izolált feldolgozófolyamatban. Támogatja add, reset, get, és delete.
[Function(nameof(Counter))]
public static Task Counter([EntityTrigger] TaskEntityDispatcher dispatcher)
{
return dispatcher.DispatchAsync(operation =>
{
if (operation.State.GetState(typeof(int)) is null)
{
operation.State.SetState(0);
}
switch (operation.Name.ToLowerInvariant())
{
case "add":
int state = operation.State.GetState<int>();
state += operation.GetInput<int>();
operation.State.SetState(state);
return new(state);
case "reset":
operation.State.SetState(0);
break;
case "get":
return new(operation.State.GetState<int>());
case "delete":
operation.State.SetState(null);
break;
}
return default;
});
}
Izolált munkafolyamat osztály alapú példája:
Az alábbi példa az entitás osztályok és metódusok használatával történő megvalósítását Counter mutatja be.
public class Counter : TaskEntity<int>
{
readonly ILogger logger;
public Counter(ILogger<Counter> logger)
{
this.logger = logger;
}
public void Add(int amount) => this.State += amount;
public void Reset() => this.State = 0;
public int Get() => this.State;
[Function(nameof(Counter))]
public Task RunEntityAsync([EntityTrigger] TaskEntityDispatcher dispatcher)
{
return dispatcher.DispatchAsync(this);
}
}
A Durable Task SDK for .NET osztályalapú szintaxissal támogatja az entitások meghatározását. Az entitás definiálásához implementálhatja az TaskEntity<TState> alaposztályt.
Az alábbi példa egy Counter , a Durable Task SDK használatával implementált entitást mutat be:
using Microsoft.DurableTask.Entities;
public class Counter : TaskEntity<int>
{
public void Add(int amount) => this.State += amount;
public void Reset() => this.State = 0;
public int Get() => this.State;
}
Az entitás regisztrálása a munkavállalónál:
builder.Services.AddDurableTaskWorker()
.AddTasks(registry =>
{
registry.AddEntity<Counter>();
})
.UseDurableTaskScheduler(connectionString);
Entitás jelzése vagy meghívása egy orkesztrátorból:
public class EntityOrchestration : TaskOrchestrator<string, int>
{
public override async Task<int> RunAsync(TaskOrchestrationContext context, string entityKey)
{
var entityId = new EntityInstanceId(nameof(Counter), entityKey);
// Signal the entity (fire-and-forget)
await context.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);
// Call the entity and wait for response
int currentValue = await context.Entities.CallEntityAsync<int>(entityId, nameof(Counter.Get));
return currentValue;
}
}
Hozzáférési entitások
Entitások elérése egyirányú vagy kétirányú kommunikációval:
- Az entitás meghívása kétirányú (oda-vissza) kommunikációt használ. Küldjön egy műveleti üzenetet az entitásnak, majd várja meg a válaszüzenetet a folytatás előtt. A válaszüzenet eredményértéket vagy hibát (például JavaScript-hibát vagy .NET kivételt) ad meg.
- Jelző egy entitás egyirányú (eldobható) kommunikációt használ. Küldjön egy műveleti üzenetet, de ne várjon a válaszra. A futtatókörnyezet garantálja a kézbesítést, de a feladó nem tudja megfigyelni az eredményértékeket és a hibákat.
Entitások elérése ügyfélfüggvényekből, vezénylő függvényekből vagy entitásfüggvényekből. Nem minden környezet támogatja mindkét kommunikációs típust:
- Az ügyfélfüggvények támogatják az entitások jelzését és az entitás állapotának olvasását.
- Az Orchestrator funkciók támogatják az entitások jelezését és hívását.
- Az entitásfüggvények támogatják az entitások jelzését.
Entitások elérése egyirányú vagy kétirányú kommunikációval:
- Az entitás meghívása kétirányú (oda-vissza) kommunikációt használ. Küldjön egy műveleti üzenetet az entitásnak, majd várja meg a válaszüzenetet a folytatás előtt. A válaszüzenet eredményértéket vagy hibát ad meg.
- Jelző egy entitás egyirányú (eldobható) kommunikációt használ. Küldjön egy műveleti üzenetet, de ne várjon a válaszra. A futtatókörnyezet garantálja a kézbesítést, de a feladó nem tudja megfigyelni az eredményértékeket és a hibákat.
Az entitások elérése ügyfelektől vagy orkesztrátoroktól. Nem minden környezet támogatja mindkét kommunikációs típust:
- Az ügyfelek támogatják az entitások jelzését és az entitás állapotának olvasását.
- A vezénylők támogatják a jelző és hívó entitásokat.
Az alábbi példák az entitások elérését mutatják be.
Példa: az ügyfél egy entitást jelez
Ha egy egyszerű Azure függvényből, más néven ügyfélfüggvényből szeretne entitásokat elérni, használja a entity ügyfélkötést. Jelen példában egy sor által aktivált függvényt mutatunk be, amely egy entitást jelez az adott kötés használatával.
Megjegyzés:
Az egyszerűség kedvéért az alábbi példák az entitásokhoz való hozzáférés lazán beírt szintaxisát mutatják be. Az entitásokat általában interfészeken keresztül érheti el, mert több típusellenőrzést biztosítanak.
Folyamatban:
Folyamatban:
[FunctionName("AddFromQueue")]
public static Task Run(
[QueueTrigger("durable-function-trigger")] string input,
[DurableClient] IDurableEntityClient client)
{
// Entity operation input comes from the queue message content.
var entityId = new EntityId(nameof(Counter), "myCounter");
int amount = int.Parse(input);
return client.SignalEntityAsync(entityId, "Add", amount);
}
Izolált munkafolyamat:
[Function("AddFromQueue")]
public static Task Run(
[QueueTrigger("durable-function-trigger")] string input,
[DurableClient] DurableTaskClient client)
{
// Entity operation input comes from the queue message content.
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
int amount = int.Parse(input);
return client.Entities.SignalEntityAsync(entityId, "Add", amount);
}
A jel kifejezés azt jelenti, hogy az entitás API-meghívása egyirányú és aszinkron. Az ügyfélfüggvények nem tudják, hogy az entitás mikor dolgozza fel a műveletet. Az ügyfélfüggvény nem tudja megfigyelni az eredményértékeket vagy a kivételeket.
Az entitások ügyféloldali eléréséhez használja az DurableTaskClient-t az entitásállapot jelzésére vagy olvasására.
// Signal an entity
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
await client.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);
A jel kifejezés azt jelenti, hogy az entitás API-meghívása egyirányú és aszinkron. Az ügyfél nem tudja, mikor dolgozza fel az entitás a műveletet.
Példa: az ügyfél beolvassa az entitás állapotát
Entitásállapot lekérdezése ügyfélfüggvényből:
Folyamatban:
[FunctionName("QueryCounter")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function)] HttpRequestMessage req,
[DurableClient] IDurableEntityClient client)
{
var entityId = new EntityId(nameof(Counter), "myCounter");
EntityStateResponse<JObject> stateResponse = await client.ReadEntityStateAsync<JObject>(entityId);
return req.CreateResponse(HttpStatusCode.OK, stateResponse.EntityState);
}
Izolált munkafolyamat:
[Function("QueryCounter")]
public static async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function)] HttpRequestData req,
[DurableClient] DurableTaskClient client)
{
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);
if (entity is null)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
HttpResponseData response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(entity);
return response;
}
Az ügyfelek lekérdezhetik egy entitás állapotát:
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
EntityMetadata<int>? entity = await client.Entities.GetEntityAsync<int>(entityId);
if (entity != null)
{
Console.WriteLine($"Current value: {entity.State}");
}
Az entitásállapot-lekérdezéseket a rendszer elküldi a tartós nyomkövetési tárolóba, és visszaadja az entitás legutóbb megőrzött állapotát. Ez az állapot mindig "véglegesített" állapot, vagyis soha nem ideiglenes köztes állapot, amelyet a művelet végrehajtása során feltételeznek. Ez az állapot azonban elavult lehet az entitás memóriabeli állapotához képest. Az entitás memóriabeli állapotát csak vezénylések olvashatják el a következő szakaszban leírtak szerint.
Példa: vezénylési jelek és entitás meghívása
Az Orchestrator-függvények az API-kkal férhetnek hozzá az entitásokhoz az orchestration trigger kötésén keresztül. Az alábbi példakód egy entitás meghívását és jelzését végző vezénylő függvényt Counter mutat be.
Folyamatban:
[FunctionName("CounterOrchestration")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var entityId = new EntityId(nameof(Counter), "myCounter");
// Two-way call to the entity which returns a value - awaits the response
int currentValue = await context.CallEntityAsync<int>(entityId, "Get");
if (currentValue < 10)
{
// One-way signal to the entity which updates the value - does not await a response
context.SignalEntity(entityId, "Add", 1);
}
}
Izolált munkafolyamat:
[Function("CounterOrchestration")]
public static async Task Run([OrchestrationTrigger] TaskOrchestrationContext context)
{
var entityId = new EntityInstanceId(nameof(Counter), "myCounter");
// Two-way call to the entity which returns a value - awaits the response
int currentValue = await context.Entities.CallEntityAsync<int>(entityId, "Get");
if (currentValue < 10)
{
// One-way signal to the entity which updates the value - does not await a response
await context.Entities.SignalEntityAsync(entityId, "Add", 1);
}
}
Csak orkesztációk hívhatnak entitásokat, és kaphatnak választ, ami lehet visszatérési érték vagy kivétel. Az ügyfélkötést használó ügyfélfüggvények csak entitásokat jelezhetnek.
Az vezénylők a környezet Entitások API-jával férhetnek hozzá az entitásokhoz:
public class CounterOrchestration : TaskOrchestrator<string, int>
{
public override async Task<int> RunAsync(TaskOrchestrationContext context, string entityKey)
{
var entityId = new EntityInstanceId(nameof(Counter), entityKey);
// Two-way call to the entity which returns a value - awaits the response
int currentValue = await context.Entities.CallEntityAsync<int>(entityId, nameof(Counter.Get));
if (currentValue < 10)
{
// One-way signal to the entity - does not await a response
await context.Entities.SignalEntityAsync(entityId, nameof(Counter.Add), 1);
}
return currentValue;
}
}
Csak a vezénylők hívhatnak meg entitásokat, és kaphatnak választ, ami lehet visszatérési érték vagy kivétel. Az ügyfelek csak entitásokat jelezhetnek.
Megjegyzés:
Egy entitás meghívása egy orchestratortól hasonló egy tevékenység meghívásához. A fő különbség az, hogy az entitások olyan tartós objektumok, amelyek címmel (entitásazonosítóval) vannak elnevezve, és támogatják a művelet nevét. A tevékenységek állapot nélküliek, és nem rendelkeznek a műveletek koncepciójával.
Példa: entitás jelzi az entitást
Az entitásfüggvények jeleket küldhetnek más entitásoknak vagy akár önmagának is, miközben egy műveletet hajtanak végre.
Módosítsa például az előző Counter entitás példáját úgy, hogy "mérföldkő-elhagyás" jelet küldjön egy monitorozó entitásnak, amikor a számláló eléri a 100-at.
Folyamatban:
case "add":
var currentValue = ctx.GetState<int>();
var amount = ctx.GetInput<int>();
if (currentValue < 100 && currentValue + amount >= 100)
{
ctx.SignalEntity(new EntityId("MonitorEntity", ""), "milestone-reached", ctx.EntityKey);
}
ctx.SetState(currentValue + amount);
break;
Izolált munkafolyamat:
case "add":
var currentValue = operation.State.GetState<int>();
var amount = operation.GetInput<int>();
if (currentValue < 100 && currentValue + amount >= 100)
{
operation.Context.SignalEntity(new EntityInstanceId("MonitorEntity", ""), "milestone-reached", operation.Context.EntityInstanceId);
}
operation.State.SetState(currentValue + amount);
break;
Entitáskoordináció
Néha több entitás műveleteinek koordinálására van szükség. Egy banki alkalmazásban például az entitások egyéni bankszámlákat jelölhetnek. Amikor pénzt utal át egyik fiókból a másikba, meg kell győződnie arról, hogy a forrásfiók rendelkezik elegendő pénzeszközzel. Mindkét fiókot egy konzisztens műveletként kell frissítenie.
Példa: Átutalási alapok (C#)
Az alábbi példakód egy vezénylő függvény használatával két számlaentitás között utal át pénzt. Az entitásfrissítések koordinálásához a LockAsync metódussal hozzon létre egy kritikus szakaszt a vezénylésben.
Megjegyzés:
Az egyszerűség kedvéért ez a példa újra felhasználja a Counter korábban definiált entitást. Egy valós alkalmazásban jobb, ha részletesebb entitást BankAccount definiál.
// This is a method called by an orchestrator function
public static async Task<bool> TransferFundsAsync(
string sourceId,
string destinationId,
int transferAmount,
IDurableOrchestrationContext context)
{
var sourceEntity = new EntityId(nameof(Counter), sourceId);
var destinationEntity = new EntityId(nameof(Counter), destinationId);
// Create a critical section to avoid race conditions.
// No operations can be performed on either the source or
// destination accounts until the locks are released.
using (await context.LockAsync(sourceEntity, destinationEntity))
{
ICounter sourceProxy =
context.CreateEntityProxy<ICounter>(sourceEntity);
ICounter destinationProxy =
context.CreateEntityProxy<ICounter>(destinationEntity);
int sourceBalance = await sourceProxy.Get();
if (sourceBalance >= transferAmount)
{
await sourceProxy.Add(-transferAmount);
await destinationProxy.Add(transferAmount);
// the transfer succeeded
return true;
}
else
{
// the transfer failed due to insufficient funds
return false;
}
}
}
A .NET-ben LockAsyncIDisposable-t ad vissza. A törlés véget vet a kritikus szakasznak. Használjon blokkot using a kritikus szakasz ábrázolásához.
Az előző példában egy vezénylő függvény pénzösszegeket ad át egy forrás entitásból egy cél entitásba. A LockAsync metódus zárolta a forrás- és célfiók-entitásokat is. Ez a zárolás biztosította, hogy egyetlen másik ügyfél sem tudta lekérdezni vagy módosítani egyik fiók állapotát sem, amíg a vezénylési logika ki nem lépett a kritikus szakaszból az using utasítás végén. Ez a működés megakadályozza a forrásszámlán a túlköltekezést.
Megjegyzés:
Amikor egy vezénylés rendes módon vagy hibával ér véget, a folyamatban lévő kritikus szakaszok implicit módon érnek véget, és a rendszer felold minden zárolást.
Kritikus szakasz viselkedése
A LockAsync metódus kritikus szakaszt hoz létre egy orchestrationban. Ezek a kritikus szakaszok megakadályozzák, hogy más vezénylések egymást átfedő módosításokat hajtsanak végre egy adott entitáskészleten. Az LockAsync API belsőleg "zárolási" műveleteket küld az entitásoknak, és azt követően ad vissza, hogy "zárolt" választ kap az egyes entitásoktól. A zárolás és a zárolás feloldása az összes entitás által támogatott beépített műveletek.
Más ügyfelek nem futtathatnak műveleteket egy entitáson, amíg zárolva van. Ez a viselkedés biztosítja, hogy egyszerre csak egy vezérlési példány zárolhasson egy entitást. Ha egy hívó megpróbál meghívni egy műveletet egy entitáson, miközben egy vezénylés zárolja, a művelet függőben lévő műveleti üzenetsorba kerül. A függőben lévő műveletek feldolgozása csak azután történik, hogy az irányítómű feloldja a zárolását.
Megjegyzés:
Ez a viselkedés kissé eltér a legtöbb programozási nyelvben használt szinkronizálási primitívektől, például a lock C# utasításától. A C#-ban például minden szálnak az utasítást kell használnia a lock megfelelő szinkronizálás biztosításához. Az entitások azonban nem követelik meg, hogy minden hívó explicit módon zároljon egy entitást. Ha bármely hívó lezár egy entitást, az azon az entitáson végzett összes többi művelet blokkolva lesz és várólistára kerül a lezárás mögött.
Az entitások zárolásai tartósak, így akkor is megmaradnak, ha a végrehajtási folyamatot újrafeldolgozzák. A rendszer egy entitás tartós állapotának részeként fenntartja a zárolásokat.
A tranzakcióktól eltérően a kritikus szakaszok nem hajtanak végre automatikusan módosításokat hibák esetén. Ehelyett írjon hibakezelést, például visszaállítást vagy újrapróbálkozást, például hibák vagy kivételek befogásával. Ez a kialakítási döntés szándékos. A vezénylés minden hatásának automatikus visszaállítása általában nehéz vagy lehetetlen, mert a vezénylések tevékenységeket futtathatnak, és olyan külső szolgáltatásokhoz fordulhatnak, amelyek nem állíthatók vissza. A visszaállítási kísérletek szintén sikertelenek lehetnek, és további hibakezelést igényelnek.
Kritikus szakaszszabályok
A legtöbb programozási nyelvben az alacsony szintű zárolási primitívekkel ellentétben a kritikus szakaszok garantáltan nem holtpontra kerülnek. A holtpontok elkerülése érdekében a következő korlátozásokat kényszerítjük ki:
- A kritikus szakaszok nem ágyazhatók be.
- A kritikus szakaszok nem hozhatnak létre al-orkesztációkat.
- A kritikus szakaszok csak a zárolt entitásokat hívhatják meg.
- A kritikus szakaszok nem hívhatják meg ugyanazt az entitást több párhuzamos hívással.
- A kritikus kódszakaszok csak a zárolási csoporton kívüli entitásokat jelezhetik.
A szabályok bármilyen megsértése futásidejű hibát okoz, például LockingRulesViolationException .NET, amely egy üzenetet tartalmaz, amely ismerteti, hogy mi volt a szabály megszegve.
Tartós entitások összehasonlítása virtuális szereplőkkel
A tartós entitások számos ötletet használnak az aktormodellből. Ha ismeri a színészeket, ebben a cikkben számos fogalmat ismerhet fel. A tartós entitások hasonlóak az Orleans-projektből származó virtuális szereplőkhöz, más néven szemcsékhez. Például:
- A tartós entitások kezelése entitásazonosító használatával történik.
- A tartós entitásműveletek sorozatosan futnak a versenyfeltételek elkerülése érdekében.
- Az entitás meghívása vagy jelezése automatikusan létrehozza.
- A futtatókörnyezet eltávolítja az entitásokat a memóriából, ha nem futtatnak műveleteket.
A főbb különbségek a következők:
- A tartós entitások előnyben részesítik a tartósságot a késéssel szemben, ezért előfordulhat, hogy nem felelnek meg a szigorú késési követelményekkel rendelkező alkalmazásoknak.
- A tartós entitások nem időtúllépést hajtanak végre az üzeneteken. Orleans az üzeneteknél időtúllépést állít be egy konfigurálható időszak után (ez alapértelmezés szerint 30 másodperc).
- Az entitások megbízhatóan és sorrendben kézbesítik az üzeneteket. Az Orleans támogatja a megbízható, rendezett kézbesítést a folyamüzenetekhez, de nem garantálja, hogy ez az összes üzenet esetében érvényes a gránumok között.
- Az orchestrációk az egyetlen hely, ahol csak kérés-válasz viszonyban használhatók az entitások. Egy entitáson belül használjon egyirányú üzenetkezelést (jelzést), mint az eredeti aktormodellben.
- A tartós entitások nem patthelyzetben maradnak. Az Orleans holtpontba kerülhet, és ezek a holtpontok fennmaradnak mindaddig, amíg az üzenetek időt nem lépnek.
- A tartós entitások tartós vezénylésekkel működnek, és támogatják az elosztott zárolási mechanizmusokat.