Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Przed napisaniem kodu w celu zaimplementowania klasy ziarna utwórz nowy projekt biblioteki klas przeznaczony dla platformy .NET Standard lub .NET Core (preferowane) lub .NET Framework 4.6.1 lub nowszej (jeśli nie można użyć platformy .NET Standard lub .NET Core ze względu na zależności). Interfejsy i klasy ziarna można zdefiniować w tym samym projekcie bibliotek klas albo w dwóch różnych projektach, aby lepiej oddzielić interfejsy od implementacji. W obu przypadkach projekty muszą odnosić się do pakietu NuGet Orleans.
Aby uzyskać bardziej szczegółowe instrukcje, zobacz sekcję Konfiguracja projektuw artykule Samouczek jeden — Orleans podstawy.
Interfejsy i klasy ziarna
Ziarna współdziałają ze sobą i można je wywoływać z zewnątrz, korzystając z metod zadeklarowanych jako część ich odpowiednich interfejsów ziaren. Klasa ziarna implementuje co najmniej jeden zadeklarowany interfejs ziarna. Wszystkie metody interfejsu ziarna muszą zwracać Task (dla void
metod), Task<TResult>lub ValueTask<TResult> (dla metod zwracających wartości typu T
).
Poniżej przedstawiono fragment przykładu Orleans usługi 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;
}
}
Limit czasu odpowiedzi dla metod ziarna
Środowisko Orleans uruchomieniowe umożliwia ustawienie limitu czasu odpowiedzi dla każdej metody ziarna. Jeśli metoda ziarna nie zostanie ukończona w przedziale czasu, środowisko uruchomieniowe zgłasza błąd TimeoutException. Aby ustawić limit czasu odpowiedzi, dodaj element ResponseTimeoutAttribute
do definicji metody ziarna w interfejsie. Niezwykle ważne jest dodanie atrybutu do definicji metody interfejsu, a nie implementacji metody w klasie ziarna, ponieważ zarówno klient, jak i silos muszą być świadomi czasu wygaśnięcia.
Rozszerzając poprzednią implementację PlayerGrain
, poniższy przykład pokazuje, jak narzucić limit czasu odpowiedzi dla metody LeaveGame
.
public interface IPlayerGrain : IGrainWithGuidKey
{
Task<IGameGrain> GetCurrentGame();
Task JoinGame(IGameGrain game);
[ResponseTimeout("00:00:05")] // 5s timeout
Task LeaveGame(IGameGrain game);
}
Powyższy kod ustawia limit czasu odpowiedzi na pięć sekund w metodzie LeaveGame
. Przy opuszczaniu gry, jeśli trwa to dłużej niż pięć sekund, nastąpi wyrzucenie TimeoutException.
Konfigurowanie limitu czasu odpowiedzi
Podobnie jak w przypadku limitów czasu odpowiedzi dla poszczególnych metod ziarna, można skonfigurować domyślny limit czasu odpowiedzi dla wszystkich metod ziarna. Wywołania metod ziarna przekroczą limit czasu, jeśli odpowiedź nie zostanie odebrana w określonym przedziale czasu. Domyślnie ten okres wynosi 30 sekund. Możesz skonfigurować domyślny limit czasu odpowiedzi:
- Konfigurując ResponseTimeout na ClientMessagingOptions, na zewnętrznym kliencie.
- Konfigurując ResponseTimeout na SiloMessagingOptions, na serwerze.
Aby uzyskać więcej informacji na temat konfigurowania Orleansprogramu , zobacz Konfiguracja klienta lub Konfiguracja serwera.
Zwrot wartości z metod ziarna
Zdefiniuj metodę ziarna zwracającą wartość typu T
w interfejsie ziarna jako zwracaną wartość Task<T>
.
W przypadku metod grain, które nie są oznaczone słowem kluczowym async
, wartość zwrotna jest zazwyczaj zwracana przy użyciu następującej instrukcji:
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
Zdefiniuj metodę ziarna, która nie zwraca żadnej wartości (efektywnie metodę void) w interfejsie ziarna jako zwracającą Task
. Zwrócony Task
element wskazuje asynchroniczne wykonanie i zakończenie metody . W przypadku metod ziarna, które nie są oznaczone słowem kluczowym async
, gdy metoda "void" zakończy swoje wykonywanie, musi zwrócić specjalną wartość Task.CompletedTask.
public Task GrainMethod2()
{
return Task.CompletedTask;
}
Metoda typu 'grain' oznaczona jako async
zwraca wartość bezpośrednio.
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
void
Metoda ziarna oznaczona jako async
, która nie zwraca żadnej wartości, po prostu kończy swoje działanie.
public async Task GrainMethod4()
{
return;
}
Jeśli metoda ziarna odbiera wartość zwracaną z innego wywołania metody asynchronicznej (do ziarna lub nie) i nie musi wykonywać obsługi błędów dla tego wywołania, może po prostu zwrócić Task
odbierane z tego asynchronicznego wywołania:
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
void
Podobnie metoda ziarna może zwrócić coś, co otrzymała od Task
innego wywołania, zamiast oczekiwania.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
ValueTask<T>
można użyć zamiast Task<T>
.
Odwołania do ziarna
Odwołanie do ziarna jest obiektem proxy implementującym ten sam interfejs ziarna co odpowiadająca mu klasa ziarna. Hermetyzuje tożsamość logiczną (typ i unikatowy klucz) ziarna docelowego. Odwołania ziarna służą do wywoływaniów ziarna docelowego. Każde odwołanie ziarna wskazuje jedno ziarno (pojedyncze wystąpienie klasy ziarna), ale można utworzyć wiele niezależnych odwołań do tego samego ziarna.
Ponieważ referencja ziarna odnosi się do logicznej tożsamości ziarna docelowego, jest niezależna od jego fizycznej lokalizacji i pozostaje ważna nawet po całkowitym ponownym uruchomieniu systemu. Można używać odnośników ziarna jak dowolnego innego obiektu .NET. Można przekazać jego do metody, użyć jej jako wartości zwracanej metody itp., a nawet zapisać ją w trwałej pamięci.
Referencję do ziarna można uzyskać, przekazując tożsamość ziarna do IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) metody, gdzie T
jest interfejsem ziarna i key
jest unikatowym kluczem ziarna w ramach swojego typu.
W poniższych przykładach pokazano, jak uzyskać odwołanie do ziarna dla interfejsu IPlayerGrain
zdefiniowanego wcześniej.
Z wewnątrz klasy ziarna:
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Z Orleans poziomu kodu klienta.
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Aby uzyskać więcej informacji na temat odwołań do ziarna, zobacz artykuł referencyjny dotyczący ziarna.
Wywołanie metody grain
Model Orleans programowania jest oparty na programowaniu asynchronicznym. Korzystając z odniesienia do ziarna z poprzedniego przykładu, oto jak wykonać wywołanie metody ziarna:
// 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);
Możesz dołączyć dwa lub więcej elementy Tasks
. Operacja sprzężenia tworzy nowy Task
, który rozwiązuje się po zakończeniu wszystkich części składowych Tasks
. Ten wzorzec jest przydatny, gdy ziarno musi uruchomić wiele obliczeń i poczekać na ukończenie wszystkich z nich przed kontynuowaniem. Na przykład, moduł front-end generujący stronę internetową z wielu części może realizować wiele wywołań w warstwie back-end (po jednym dla każdej części) i otrzymywać Task
dla każdego wyniku. Ziarno będzie następnie czekać na sprzężenie wszystkich tych Tasks
elementów . Gdy rozpoznane zostanie sprzężone Task
, indywidualne Tasks
zostały ukończone, a wszystkie dane wymagane do sformatowania strony internetowej zostały odebrane.
Przykład:
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.
Propagacja błędu
Gdy metoda ziarna zgłasza wyjątek, Orleans propaguje ten wyjątek w górę stosu wywołującego, w razie potrzeby między hostami. Aby działało zgodnie z zamierzeniami, wyjątki muszą być serializowane przez Orleans, a hosty obsługujące wyjątek muszą mieć dostęp do typu wyjątku. Jeśli typ wyjątku jest niedostępny, Orleans zgłasza wyjątek jako wystąpienie Orleans.Serialization.UnavailableExceptionFallbackException, zachowując komunikat, typ i ślad stosu oryginalnego wyjątku.
Wyjątki zgłaszane z metod ziarna nie powodują dezaktywowania ziarna, chyba że wyjątek dziedziczy z Orleans.Storage.InconsistentStateException. Operacje magazynowania zgłaszają błąd InconsistentStateException
, gdy odkryją, że stan ziarna w pamięci operacyjnej jest niespójny ze stanem w bazie danych. Oprócz specjalnej obsługi dla InconsistentStateException
, to zachowanie jest podobne do zgłaszania wyjątku od dowolnego obiektu platformy .NET: wyjątki nie powodują zniszczenia obiektu.
Metody wirtualne
Klasa Grain może ewentualnie zastąpić wirtualne metody OnActivateAsync i OnDeactivateAsync. Środowisko Orleans uruchomieniowe wywołuje te metody po aktywacji i dezaktywacji każdego ziarna w klasie. Daje to możliwość na wykonanie dodatkowych operacji inicjalizacji i czyszczenia kodu grain. Wyrzucenie wyjątku przez OnActivateAsync
powoduje niepowodzenie procesu aktywacji.
Chociaż OnActivateAsync
(jeśli przesłonięta) jest zawsze wywoływana w ramach procesu aktywacji ziarna, nie ma gwarancji, że OnDeactivateAsync
zostanie wywołana we wszystkich sytuacjach (na przykład w przypadku awarii serwera lub innych nietypowych zdarzeń). W związku z tym aplikacje nie powinny polegać na OnDeactivateAsync
wykonywaniu operacji krytycznych, takich jak utrwalanie zmian stanu. Używaj go tylko w przypadku operacji najwydajniejszej pracy.