Sdílet prostřednictvím


Vývoj odstupňovaného

Před napsáním kódu pro implementaci třídy grain vytvořte nový projekt knihovny tříd, který cílí na .NET Standard nebo .NET Core (upřednostňovaný) nebo .NET Framework 4.6.1 nebo vyšší (pokud nemůžete použít .NET Standard nebo .NET Core kvůli závislostem). Rozhraní a třídy zrnitosti můžete definovat ve stejném projektu knihovny tříd nebo ve dvou různých projektech pro lepší oddělení rozhraní od implementace. V obou případech musí projekty odkazovat na Microsoft.Orleans.Sdk NuGet balíček.

Podrobnější pokyny najdete v části Nastavení projektukurzu One – Orleans Základy.

Rozhraní a třídy zrna

Zrna vzájemně komunikují a volají se odjinud vyvoláním metod deklarovaných jako součást příslušných rozhraní zrn. Třída zrno implementuje jedno nebo více dříve deklarovaných zrnových rozhraní. Všechny metody rozhraní zrnitosti musí vracet Task (pro void metody), a Task<TResult>nebo a ValueTask<TResult> (pro metody vracející hodnoty typu T).

Následuje výňatek z ukázky Orleans služby Presence Service:

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();

    Task JoinGame(IGameGrain game);

    Task LeaveGame(IGameGrain game);
}

public class PlayerGrain : Grain, IPlayerGrain
{
    private IGameGrain _currentGame;

    // Game the player is currently in. May be null.
    public Task<IGameGrain> GetCurrentGame()
    {
       return Task.FromResult(_currentGame);
    }

    // Game grain calls this method to notify that the player has joined the game.
    public Task JoinGame(IGameGrain game)
    {
       _currentGame = game;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} joined game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
    }

   // Game grain calls this method to notify that the player has left the game.
   public Task LeaveGame(IGameGrain game)
   {
       _currentGame = null;

       Console.WriteLine(
           $"Player {GetPrimaryKey()} left game {game.GetPrimaryKey()}");

       return Task.CompletedTask;
   }
}

Vypršení časového limitu odezvy pro metody zrna

Běhové prostředí Orleans vám umožňuje vynutit časový limit odezvy na každou metodu zrnitosti. Pokud se v časovém limitu nedokončí grain metoda, modul runtime vyvolá TimeoutException. Chcete-li uložit časový limit odezvy, přidejte ResponseTimeoutAttribute do definice zrnkového metodu rozhraní. Je důležité přidat atribut do definice metody rozhraní, nikoli do implementace metody ve třídě grain, protože jak klient, tak silo musí mít povědomí o časovém limitu.

Rozšíření předchozí PlayerGrain implementace, následující příklad ukazuje, jak uložit časový limit odpovědi pro metodu LeaveGame :

public interface IPlayerGrain : IGrainWithGuidKey
{
    Task<IGameGrain> GetCurrentGame();

    Task JoinGame(IGameGrain game);

    [ResponseTimeout("00:00:05")] // 5s timeout
    Task LeaveGame(IGameGrain game);
}

Předchozí kód nastaví pro metodu LeaveGame časový limit odpovědi 5 sekund. Pokud opuštění hry trvá déle než pět sekund, je vyhozen(a) TimeoutException.

Konfigurace časového limitu odpovědi

Podobně jako u časových limitů odpovědí jednotlivých metod agregace můžete nakonfigurovat výchozí časový limit odpovědi pro všechny metody agregace. Pokud odpověď není přijata v zadaném období, volání metod agregace vyprší. Ve výchozím nastavení je toto období 30 sekund. Můžete nakonfigurovat výchozí časový limit odpovědi:

Další informace o konfiguraci Orleansnaleznete v tématu Konfigurace klienta nebo Konfigurace serveru.

Vrácené hodnoty z grainových metod

Definujte metodu grainu, která vrací hodnotu typu T v rozhraní grainu jako že vrací Task<T>. Pro metody zpracování dat, které nejsou označeny klíčovým slovem async, pokud je vrácená hodnota k dispozici, obvykle ji vrátíte pomocí následujícího příkazu:

public Task<SomeType> GrainMethod1()
{
    return Task.FromResult(GetSomeType());
}

Definujte metodu typu grain, která v rámci rozhraní nevrací žádnou hodnotu (tj. metodu typu void), tak, aby měla návratový typ Task. Task Vrácená indikuje asynchronní spuštění a dokončení metody. U metod zrna, které nejsou označeny klíčovým slovem async, musí po dokončení provádění metoda "void" vrátit speciální hodnotu Task.CompletedTask.

public Task GrainMethod2()
{
    return Task.CompletedTask;
}

Metoda zrnitosti označená jako async vrátí hodnotu přímo:

public async Task<SomeType> GrainMethod3()
{
    return await GetSomeTypeAsync();
}

A void metoda označená jako async, která nevrací žádnou hodnotu, se jednoduše ukončí na konci svého spuštění.

public async Task GrainMethod4()
{
    return;
}

Pokud metoda pro grain obdrží návratovou hodnotu z jiného asynchronního volání metody (buď na grain, nebo ne), a nepotřebuje provádět zpracování chyb pro toto volání, může jednoduše vrátit Task, kterou obdrží z daného asynchronního volání:

public Task<SomeType> GrainMethod5()
{
    Task<SomeType> task = CallToAnotherGrain();

    return task;
}

Podobně může void zrnitý způsob vrátit Task, které bylo vráceno jiným voláním, místo aby na něj čekal.

public Task GrainMethod6()
{
    Task task = CallToAsyncAPI();
    return task;
}

ValueTask<T> lze použít místo Task<T>.

Odkazy na agregace

Odkaz na zrno je objekt proxy, který implementuje stejné rozhraní zrna jako odpovídající třída zrna. Zapouzdřuje logickou identitu (typ a jedinečný klíč) cílového grainu. K volání cílového agregačního intervalu se používají odkazy na agregační intervaly. Každý odkaz na zrno odkazuje na jedno zrno (jedna instance třídy zrna), ale můžete vytvořit více nezávislých odkazů na stejné zrno.

Vzhledem k tomu, že odkaz na grain představuje logickou identitu cílového grainu, je nezávislý na fyzickém umístění grainu a zůstává platný i po úplném restartování systému. Odkazy na objekty typu Grain můžete použít stejně jako jakýkoli jiný objekt .NET. Můžete ji předat metodě, použít ji jako návratovou hodnotu metody atd., a dokonce ji uložit do trvalého úložiště.

Referenci zrna můžete získat předáním identity zrna metodě IGrainFactory.GetGrain<TGrainInterface>(Type, Guid), kde T je rozhraní zrna a key je jedinečný klíč zrna v rámci jeho typu.

Následující příklady ukazují, jak získat referenční informace o IPlayerGrain agregačním rozhraní definovaném dříve.

Z nitra třídy o zrninách:

IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);

Z Orleans klientského kódu.

IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);

Další informace o referencích na zrno najdete v článku o referencích na zrno.

Vyvolání metody Grain

Programovací Orleans model je založený na asynchronním programování. Pomocí odkazu na zrnitost z předchozího příkladu provedete vyvolání metody zrnitosti:

// Invoking a grain method asynchronously
Task joinGameTask = player.JoinGame(this);

// The await keyword effectively makes the remainder of the
// method execute asynchronously at a later point
// (upon completion of the Task being awaited) without blocking the thread.
await joinGameTask;

// The next line will execute later, after joinGameTask has completed.
players.Add(playerId);

Můžete spojit dva nebo více Tasks. Operace spojení vytvoří novou Task, která se vyřeší, když se dokončí všechny její složky Tasks. Tento vzor je užitečný v případě, že je potřeba spustit několik výpočtů a počkat na dokončení všech z nich, než bude pokračováno. Například front-endový úkol, který generuje webovou stránku z mnoha částí, může provádět více back-endových volání (jedno pro každou část) a přijímat Task pro každý výsledek. Zrno by pak čekalo na spojení všech těchto Tasks. Po vyřešení spojení Task byly jednotlivé prvky Tasks dokončeny a veškerá data potřebná k naformátování webové stránky byla přijata.

Příklad:

List<Task> tasks = new List<Task>();
Message notification = CreateNewMessage(text);

foreach (ISubscriber subscriber in subscribers)
{
    tasks.Add(subscriber.Notify(notification));
}

// WhenAll joins a collection of tasks, and returns a joined
// Task that will be resolved when all of the individual notification Tasks are resolved.
Task joinedTask = Task.WhenAll(tasks);

await joinedTask;

// Execution of the rest of the method will continue
// asynchronously after joinedTask is resolve.

Šíření chyb

Když metoda grainu vyvolá výjimku, Orleans tuto výjimku rozšíří po volacím zásobníku a mezi hostiteli podle potřeby. Aby to fungovalo podle očekávání, výjimky musí být serializovatelné pomocí Orleansa hostitelé, kteří zpracovávají výjimku, musí mít k dispozici typ výjimky. Pokud typ výjimky není k dispozici, Orleans vyvolá výjimku jako instanci Orleans.Serialization.UnavailableExceptionFallbackException, a tím zachovává zprávu, typ a trasování zásobníku původní výjimky.

Výjimky vyvolané metodami zrna nezpůsobí deaktivaci zrna, pokud výjimka nedědí z Orleans.Storage.InconsistentStateException. Operace úložiště můžou vyvolat InconsistentStateException , když zjistí, že stav zrnka v paměti je nekonzistentní se stavem v databázi. Kromě speciálního InconsistentStateExceptionzpracování je toto chování podobné vyvolání výjimky z jakéhokoli objektu .NET: výjimky nezpůsobí zničení objektu.

Virtuální metody

Třída zrnitosti může volitelně přepsat OnActivateAsync a OnDeactivateAsync virtuální metody. Modul Orleans runtime vyvolá tyto metody při aktivaci a deaktivaci každého zrna třídy. Díky tomu má váš kód pro grain příležitost provádět další operace inicializace a čištění. Aktivace selže kvůli výjimce OnActivateAsync.

I když OnActivateAsync (pokud je přepsáno) se vždy volá jako součást procesu aktivace grainu, není zaručeno, že se OnDeactivateAsync zavolá ve všech situacích (například v případě selhání serveru nebo jiných neobvyklých událostí). Z tohoto důvodu by se vaše aplikace neměly spoléhat na OnDeactivateAsync provádění kritických operací, jako jsou trvalé změny stavu. Používejte ho jenom pro operace s maximálním úsilím.

Viz také