Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Os grãos em Orleans têm, cada um, um identificador único, exclusivo e definido pelo utilizador, que consiste em duas partes:
- O nome do tipo de grão, identificando exclusivamente a classe de grãos.
- A chave de grão, identificando exclusivamente uma instância lógica dessa classe de grão.
Orleans representa o tipo de grão e a chave como cadeias de caracteres legíveis por humanos. Por convenção, escreva a identidade do grão com o tipo de grão e a chave separados por um /
caractere. Por exemplo, shoppingcart/bob65
representa o tipo de grão nomeado shoppingcart
com a chave bob65
.
Construir identidades de grãos diretamente é incomum. Alternativamente, criar referências de granularidade usando Orleans.IGrainFactory é mais comum.
As seções a seguir discutem nomes de tipos de grãos e chaves de grão com mais detalhes.
Nomes de tipos de grãos
Orleans Cria um nome de tipo de grão com base na classe de implementação de grão. Ele remove o sufixo "Grain" do nome da classe, se presente, e converte a cadeia de caracteres resultante em sua representação minúscula. Por exemplo, uma classe denominada ShoppingCartGrain
recebe o tipo de grão shoppingcart
. Recomenda-se que os nomes e chaves de tipo de grão consistam apenas em caracteres imprimíveis, como caracteres alfanuméricos (a
-z
, A
-Z
e 0
-9
) e símbolos como -
, _
, @
e =
. Outros caracteres podem não ser suportados e muitas vezes requerem tratamento especial quando impressos em logs ou aparecendo como identificadores em outros sistemas, como bancos de dados.
Como alternativa, use o Orleans.GrainTypeAttribute atributo para personalizar o nome do tipo de grão para a classe de grão à qual ele está anexado, conforme mostrado no exemplo a seguir:
[GrainType("cart")]
public class ShoppingCartGrain : IShoppingCartGrain
{
// Add your grain implementation here
}
No exemplo anterior, a classe de grão ShoppingCartGrain
tem o nome do tipo de grão cart
. Cada grão só pode ter um nome de tipo de grão.
Para grãos genéricos, inclua a aridade genérica no nome do tipo de grão. Por exemplo, considere a seguinte DictionaryGrain<K, V>
classe:
[GrainType("dict`2")]
public class DictionaryGrain<K, V> : IDictionaryGrain<K, V>
{
// Add your grain implementation here
}
A classe grain tem dois parâmetros genéricos, então um backtick `
seguido pela aridade genérica, 2, é adicionado ao final do nome dict
do tipo grain para criar o nome dict`2
do tipo grain. Isto é especificado no atributo na classe de grãos: [GrainType("dict
2")]».
Chaves de grão
Por conveniência, Orleans expõe métodos que permitem a construção de grain keys a partir de um Guid ou Int64, para além de um String. A chave primária tem como escopo o tipo de grão. Portanto, a identidade completa de um grão se forma a partir de seu tipo e chave.
O chamador do grão decide qual esquema usar. As opções são:
Como os dados subjacentes são os mesmos, os esquemas podem ser usados de forma intercambiável: todos eles são codificados como strings.
Situações que exigem uma instância de grão singleton podem usar um valor fixo bem conhecido, como "default"
. Esta é apenas uma convenção, mas aderir a ela esclarece no local de chamada que um grão singleton está em uso.
Usando identificadores globais exclusivos (GUIDs) como chaves
System.Guid Crie chaves úteis quando a aleatoriedade e a exclusividade global forem desejadas, como ao criar um novo trabalho em um sistema de processamento de trabalho. Não é necessário coordenar a alocação de chaves, o que poderia introduzir um único ponto de falha ou um bloqueio do lado do sistema em um recurso, potencialmente criando um gargalo. A chance de colisões GUID é muito baixa, tornando-os uma escolha comum ao arquitetar sistemas que precisam de alocação de identificador aleatório.
Referenciando um grão por GUID no código do cliente:
var grain = grainFactory.GetGrain<IExample>(Guid.NewGuid());
Recuperando a chave primária do código de grão:
public override Task OnActivateAsync()
{
Guid primaryKey = this.GetPrimaryKey();
return base.OnActivateAsync();
}
Usando inteiros como chaves
Um inteiro longo também está disponível. Isso faz sentido se o grão persistir em um banco de dados relacional, onde os índices numéricos são frequentemente preferidos em relação aos GUIDs.
Referenciando um grão por um inteiro longo no código do cliente:
var grain = grainFactory.GetGrain<IExample>(1);
Recuperando a chave primária do código de grão:
public override Task OnActivateAsync()
{
long primaryKey = this.GetPrimaryKeyLong();
return base.OnActivateAsync();
}
Usando cadeias de caracteres como teclas
Uma chave de texto também está disponível.
Fazendo referência a um grão por String no código do cliente:
var grain = grainFactory.GetGrain<IExample>("myGrainKey");
Recuperando a chave primária do código de grão:
public override Task OnActivateAsync()
{
string primaryKey = this.GetPrimaryKeyString();
return base.OnActivateAsync();
}
Usando chaves compostas
Se o sistema não se encaixar bem com GUIDs ou longs, opte por uma chave primária composta. Isso permite usar uma combinação de um GUID ou long e uma string para fazer referência a um grão.
Herdar a interface de IGrainWithGuidCompoundKey ou IGrainWithIntegerCompoundKey desta forma:
public interface IExampleGrain : Orleans.IGrainWithIntegerCompoundKey
{
Task Hello();
}
No código do cliente, isso adiciona um segundo argumento ao IGrainFactory.GetGrain método na fábrica de grãos:
var grain = grainFactory.GetGrain<IExample>(0, "a string!", null);
Para aceder à chave composta no grain, chame uma sobrecarga do método GrainExtensions.GetPrimaryKey (como GrainExtensions.GetPrimaryKeyLong):
public class ExampleGrain : Orleans.Grain, IExampleGrain
{
public Task Hello()
{
long primaryKey = this.GetPrimaryKeyLong(out string keyExtension);
Console.WriteLine($"Hello from {keyExtension}");
return Task.CompletedTask;
}
}
Por que os grãos usam identificadores lógicos
Em ambientes orientados a objetos como o .NET, a identidade de um objeto é difícil de distinguir de uma referência a ele. Quando um objeto é criado usando a palavra-chave new
, a referência retornada representa todos os aspetos de sua identidade, exceto aqueles que mapeiam o objeto para alguma entidade externa que ele representa.
Orleans é projetado para sistemas distribuídos. Em sistemas distribuídos, as referências de objeto não podem representar a identidade da instância porque estão limitadas ao espaço de endereçamento de um único processo.
Orleans usa identificadores lógicos para evitar essa limitação. Os grãos usam identificadores lógicos para que as referências de grãos permaneçam válidas durante toda a vida útil do processo e sejam portáteis de um processo para outro. Isso permite que eles sejam armazenados e posteriormente recuperados, ou enviados através de uma rede para outro processo no aplicativo, tudo isso sem deixar de se referir à mesma entidade: o grão para o qual a referência foi criada.