Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Avant d’écrire du code pour implémenter une classe de grain, créez un projet bibliothèque de classes ciblant .NET Standard ou .NET Core (préféré), ou .NET Framework 4.6.1 ou version ultérieure (si vous ne pouvez pas utiliser .NET Standard ou .NET Core en raison de dépendances). Vous pouvez définir des interfaces de grain et des classes de grain dans le même projet de bibliothèque de classes ou dans deux projets différents pour mieux séparer les interfaces de l’implémentation. Dans les deux cas, les projets doivent référencer le package NuGet Microsoft.Orleans.SDK.
Pour obtenir des instructions plus détaillées, consultez la section Paramétrage du projet du Tutoriel Un – Orleans Les bases.
Interfaces et classes de grain
Les grains interagissent entre eux et sont appelés de l’extérieur en appelant des méthodes déclarées dans le cadre de leurs interfaces de grain respectives. Une classe de grain implémente une ou plusieurs interfaces de grain déclarées précédemment. Toutes les méthodes d’une interface de grain doivent retourner un Task (pour void les méthodes), un Task<TResult>ou un ValueTask<TResult> (pour les méthodes retournant des valeurs de type T).
Voici un extrait de l’exemple Orleans 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;
}
}
Délai d’expiration de réponse pour les méthodes "grain"
Le runtime Orleans vous permet d’appliquer un délai d’expiration de réponse par méthode de grain. Si une méthode de grain ne se termine pas dans le temps limite, l'environnement d'exécution lève une exception TimeoutException. Pour imposer un délai d’expiration de réponse, ajoutez la ResponseTimeoutAttribute à la définition de la méthode de grain de l’interface. Il est essentiel d’ajouter l’attribut à la définition de méthode d’interface, et non l’implémentation de la méthode dans la classe de grain, car le client et le silo doivent être conscients du délai d’expiration.
L’extension de l’implémentation PlayerGrain précédente montre comment imposer un délai d’attente de réponse à la méthode LeaveGame :
public interface IPlayerGrain : IGrainWithGuidKey
{
Task<IGameGrain> GetCurrentGame();
Task JoinGame(IGameGrain game);
[ResponseTimeout("00:00:05")] // 5s timeout
Task LeaveGame(IGameGrain game);
}
Le code précédent définit un délai d’expiration de réponse de cinq secondes sur la méthode LeaveGame. Lorsque vous quittez un jeu, s'il faut plus de cinq secondes, une TimeoutException est déclenchée.
Configurer le délai d’expiration de réponse
Comme pour les délais d’expiration de réponse de méthode de grain individuels, vous pouvez configurer un délai d’expiration de réponse par défaut pour toutes les méthodes de grain. Les appels aux méthodes de grain expirent si une réponse n’est pas reçue dans le délai spécifié. Par défaut, cette période est 30 secondes. Vous pouvez configurer le délai d’expiration de réponse par défaut :
- En configurant ResponseTimeout sur ClientMessagingOptions, depuis un client externe.
- En configurant ResponseTimeout sur SiloMessagingOptionssur un serveur.
Pour plus d’informations sur la configuration de Orleans, consultez de configuration du client ou configuration du serveur.
Valeurs retournées par les méthodes de grain
Définissez une méthode de grain qui retourne une valeur de type T dans une interface de grain comme renvoyant un Task<T>.
Pour les méthodes de grain non marquées avec le async mot clé, lorsque la valeur de retour est disponible, vous le renvoyez généralement à l’aide de l’instruction suivante :
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
Définissez une méthode de grain qui ne retourne aucune valeur (effectivement une méthode void) dans une interface de grain comme renvoyant un Task. Le retour Task indique l’exécution asynchrone et l’achèvement de la méthode. Pour les méthodes de grain non marquées avec le async mot clé, lorsqu’une méthode « void » termine son exécution, elle doit retourner la valeur Task.CompletedTaskspéciale :
public Task GrainMethod2()
{
return Task.CompletedTask;
}
Une méthode de grain marquée comme async retourne directement la valeur :
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
Une méthode de grain void marquée comme async ne retournant aucune valeur arrive simplement à la fin de son exécution.
public async Task GrainMethod4()
{
return;
}
Si une méthode grain reçoit la valeur de retour d’un autre appel de méthode asynchrone (vers un grain ou non) et n’a pas besoin d’effectuer la gestion des erreurs pour cet appel, elle peut simplement renvoyer la valeur qu’elle reçoit de cet appel asynchrone.
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
De même, une méthode de grain void peut retourner une Task retournée par un autre appel au lieu de l’attendre.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
ValueTask<T> pouvez être utilisé au lieu de Task<T>.
Références de céréale
Une référence de grain est un objet proxy implémentant la même interface de grain que la classe de grain correspondante. Il encapsule l’identité logique (type et clé unique) du grain cible. Vous utilisez des références de grain pour effectuer des appels au grain cible. Chaque référence de grain pointe vers un seul grain (une seule instance de la classe de grain), mais vous pouvez créer plusieurs références indépendantes au même grain.
Étant donné qu’une référence de grain représente l’identité logique du grain cible, elle est indépendante de l’emplacement physique du grain et reste valide même après un redémarrage complet du système. Vous pouvez utiliser des références de grain comme n’importe quel autre objet .NET. Vous pouvez le transmettre à une méthode, l’utiliser comme valeur de retour de méthode, etc., et même l’enregistrer dans un stockage persistant.
Vous pouvez obtenir une référence de grain en transmettant l’identité d’un grain à la IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) méthode, où T est l’interface de grain et key est la clé unique du grain dans son type.
Les exemples suivants montrent comment obtenir une référence de grain pour l’interface IPlayerGrain définie précédemment.
Depuis l'intérieur d'une classe de grain :
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Du code client Orleans.
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
Pour plus d’informations sur les références de grain, consultez l’article de référence sur les grains .
Appel de méthode grain
Le modèle de programmation Orleans est basé sur de programmation asynchrone. À l’aide de la référence de grain de l’exemple précédent, voici comment effectuer un appel de méthode de grain :
// 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);
Vous pouvez joindre deux ou plusieurs Tasks. L'opération de jointure crée un nouveau Task qui se résout lorsque tous ses composants Tasks sont terminés. Ce modèle est utile lorsqu’un grain doit démarrer plusieurs calculs et attendre qu’ils se terminent avant de continuer. Par exemple, un grain frontal générant une page web composée de plusieurs composants peut effectuer plusieurs appels principaux (un pour chaque partie) et recevoir un Task pour chaque résultat. Le grain attendrait alors la jointure de tous ces Tasks. Lorsque la jointure Task est résolue, l’individu Tasks a terminé et toutes les données requises pour mettre en forme la page web ont été reçues.
Exemple:
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.
Propagation d’erreurs
Lorsqu’une méthode de grain lève une exception, Orleans propage cette exception dans la pile appelante, à travers les hôtes si nécessaire. Pour que cela fonctionne comme prévu, les exceptions doivent être sérialisables par Orleans, et les hôtes qui gèrent l’exception doivent avoir le type d’exception disponible. Si un type d’exception n’est pas disponible, Orleans lève l’exception en tant qu’instance de Orleans.Serialization.UnavailableExceptionFallbackException, en conservant le message, le type et la trace de pile de l’exception d’origine.
Les exceptions levées à partir de méthodes de grain ne provoquent pas la désactivation du grain, sauf si l’exception hérite de Orleans.Storage.InconsistentStateException. Les opérations de stockage lèvent InconsistentStateException lorsqu’elles découvrent que l’état en mémoire du grain est incohérent avec l’état de la base de données. Outre la gestion spéciale de InconsistentStateException, ce comportement est similaire à la levée d’une exception à partir d’un objet .NET : les exceptions ne provoquent pas la destruction d’un objet.
Méthodes virtuelles
Une classe de grain peut remplacer facultativement les méthodes virtuelles OnActivateAsync et OnDeactivateAsync. Le Orleans runtime appelle ces méthodes lors de l’activation et de la désactivation de chaque grain de la classe. Cela permet à votre code grain d’effectuer des opérations d’initialisation et de nettoyage supplémentaires. Une exception levée par OnActivateAsync empêche le processus d’activation.
Bien que OnActivateAsync (en cas de substitution) soit toujours appelé dans le cadre du processus d’activation du grain, OnDeactivateAsync n'est pas garanti d'être appelé dans toutes les situations, par exemple en cas de défaillance du serveur ou d'autres événements anormaux. En raison de cela, vos applications ne doivent pas s’appuyer sur OnDeactivateAsync l’exécution d’opérations critiques, telles que la persistance des modifications d’état. Utilisez-le uniquement pour les opérations optimales.
Voir aussi
- Extensions de grain
- Identité du grain
- références grain
- persistance des grains
- vue d’ensemble du cycle de vie des grains
- Placement des grains