Formação
Módulo
Crie seu primeiro aplicativo de Orleans com o ASP.NET Core 8.0 - Training
Saiba como criar aplicativos distribuídos nativos da nuvem com Orleans.
Este browser já não é suportado.
Atualize para o Microsoft Edge para tirar partido das mais recentes funcionalidades, atualizações de segurança e de suporte técnico.
Antes de escrever código para implementar uma classe de grãos, crie um novo projeto class Library direcionado para .NET Standard ou .Net Core (preferencial) ou .NET Framework 4.6.1 ou superior (se não puder utilizar .NET Standard ou .NET Core devido a dependências). As interfaces de grãos e as classes de cereais podem ser definidas no mesmo projeto da Biblioteca de Classes, ou em dois projetos diferentes para uma melhor separação das interfaces da implementação. Em qualquer dos casos, os projetos precisam de fazer referência aos pacotes Microsoft.Orleans.Core.Abstractions e Microsoft.Orleans.CodeGenerator.MSBuild NuGet.
Para obter instruções mais detalhadas, consulte a secção de configuração Project do Tutorial One – Orleans Basics.
Os grãos interagem entre si e são chamados de fora invocando métodos declarados como parte das respetivas interfaces de grãos. Uma classe de grão implementa uma ou mais interfaces de grãos previamente declaradas. Todos os métodos de interface de grão devem devolver um (para void
métodos), a Task<TResult> ou um ValueTask<TResult> (para métodos que retornem valores do tipoT
).Task
Segue-se um excerto da amostra do Serviço de Presença 1.5 de Orleans:
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;
}
}
Um método de grão que devolve um valor do tipo T
é definido numa interface de grão como devolvendo a Task<T>
.
Para os métodos de grão não marcados com a async
palavra-chave, quando o valor de retorno está disponível, é geralmente devolvido através da seguinte declaração:
public Task<SomeType> GrainMethod1()
{
return Task.FromResult(GetSomeType());
}
Um método de grão que não devolva qualquer valor, efetivamente um método nulo, é definido numa interface de grão como devolvendo a Task
. A detenção Task
indica execução assíncrona e conclusão do método. Para os métodos de grão não marcados com a async
palavra-chave, quando um método "vazio" completa a sua execução, tem de devolver o valor especial de Task.CompletedTask:
public Task GrainMethod2()
{
return Task.CompletedTask;
}
Um método de grão marcado como async
devolve o valor diretamente:
public async Task<SomeType> GrainMethod3()
{
return await GetSomeTypeAsync();
}
Um void
método de grão marcado como async
que não devolve qualquer valor simplesmente regressa no final da sua execução:
public async Task GrainMethod4()
{
return;
}
Se um método de grão receber o valor de devolução de outra chamada de método assíncrona, para um grão ou não, e não precisar de executar o tratamento de erros dessa chamada, pode simplesmente devolver o Task
que recebe dessa chamada assíncrona:
public Task<SomeType> GrainMethod5()
{
Task<SomeType> task = CallToAnotherGrain();
return task;
}
Da mesma forma, um void
método de grão pode devolver-lhe um Task
retorno por outra chamada em vez de aguardar.
public Task GrainMethod6()
{
Task task = CallToAsyncAPI();
return task;
}
ValueTask<T>
pode ser usado em vez de Task<T>
.
Uma Referência de Grão é um objeto proxy que implementa a mesma interface de grão que a classe de grão correspondente. Encapsula a identidade lógica (tipo e chave única) do grão-alvo. Uma referência de grão é usada para fazer chamadas para o grão-alvo. Cada referência de grão é a um único grão (um único exemplo da classe de grãos), mas pode-se criar múltiplas referências independentes ao mesmo grão.
Uma vez que uma referência de grão representa a identidade lógica do grão-alvo, é independente da localização física do grão, e permanece válido mesmo após um reinício completo do sistema. Os desenvolvedores podem usar referências de grãos como qualquer outro objeto .NET. Pode ser passado para um método, usado como um valor de retorno do método, etc., e até mesmo guardado para armazenamento persistente.
Uma referência de grão pode ser obtida passando a identidade de um grão para o IGrainFactory.GetGrain<TGrainInterface>(Type, Guid) método, onde T
está a interface de grão e key
é a chave única do grão dentro do tipo.
Seguem-se exemplos de como obter uma referência de grão da IPlayerGrain
interface acima definida.
De dentro de uma classe de cereais:
IPlayerGrain player = GrainFactory.GetGrain<IPlayerGrain>(playerId);
Do código do cliente de Orleans.
IPlayerGrain player = client.GetGrain<IPlayerGrain>(playerId);
O modelo de programação de Orleans baseia-se na programação assíncroa. Utilizando a referência de grãos do exemplo anterior, eis como realizar uma invocação do método de grão:
// 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);
É possível juntar-se a dois ou mais Tasks
; a operação de junção cria uma nova Task
que se resolve quando todos os seus constituintes Task
estão concluídos. Este é um padrão útil quando um grão precisa iniciar várias computações e esperar que todos eles completem antes de prosseguir. Por exemplo, um grão frontal que gere uma página web feita de muitas partes pode fazer várias chamadas traseiras, uma para cada parte, e receber um Task
para cada resultado. O grão aguarda então a junção de todos estes Tasks
; quando a junção Task
for resolvida, os indivíduos Task
foram concluídos, e todos os dados necessários para o formato da página web foram recebidos.
Exemplo:
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.
Uma classe de grãos pode opcionalmente sobrepor-se OnActivateAsync e OnDeactivateAsync métodos virtuais; estes são invocados pelo tempo de execução de Orleães após a ativação e desativação de cada grão da classe. Isto dá ao código de cereais a oportunidade de realizar operações adicionais de inicialização e limpeza. Uma exceção lançada por OnActivateAsync
falha no processo de ativação.
Embora OnActivateAsync
, se ultrapassado, seja sempre chamado como parte do processo de ativação de grãos, OnDeactivateAsync
não é garantido que seja chamado em todas as situações, por exemplo, em caso de falha do servidor ou outro evento anormal. Por isso, as candidaturas não devem contar OnDeactivateAsync
com a realização de operações críticas, como a persistência de alterações estatais. Devem usá-lo apenas para as operações de melhor esforço.
Formação
Módulo
Crie seu primeiro aplicativo de Orleans com o ASP.NET Core 8.0 - Training
Saiba como criar aplicativos distribuídos nativos da nuvem com Orleans.