Compartir a través de


Identidad de grano

Los granos de Orleans tienen cada uno un identificador único definido por el usuario que consta de dos partes:

  1. Nombre del tipo de grano, que identifica de forma única la clase de grano.
  2. Clave de grano, que identifica de forma única una instancia lógica de esa clase de grano.

Orleans representa tanto el tipo de grano como la clave como cadenas legibles. Por convención, escriba la identidad del grano con el tipo de grano y la clave separados por el carácter /. Por ejemplo, shoppingcart/bob65 representa el tipo de grano denominado shoppingcart con la clave bob65.

La construcción directa de identidades de grano es poco frecuente. En su lugar, la creación de referencias de grano mediante Orleans.IGrainFactory es más común.

En las secciones siguientes se describen los nombres de tipos específicos y las claves de grano con más detalle.

Nombres de tipo de grano

Orleans crea un nombre de tipo de grano basado en la clase de implementación de grano. Quita el sufijo "Grain" del nombre de clase, si está presente, y convierte la cadena resultante en su representación en minúsculas. Por ejemplo, una clase denominada ShoppingCartGrain recibe el nombre shoppingcartdel tipo de grano . Se recomienda que los nombres de tipo de grano y las claves solo consten de caracteres imprimibles, como caracteres alfanuméricos (a-z, A-Z y 0-9) y símbolos como -, _, @ y =. Es posible que no se admita otros caracteres y, a menudo, requieran un tratamiento especial cuando se imprimen en registros o aparecen como identificadores en otros sistemas, como bases de datos.

Como alternativa, use el Orleans.GrainTypeAttribute atributo para personalizar el nombre del tipo de grano para la clase de grano a la que está asociado, como se muestra en el ejemplo siguiente:

[GrainType("cart")]
public class ShoppingCartGrain : IShoppingCartGrain
{
    // Add your grain implementation here
}

En el ejemplo anterior, la clase ShoppingCartGrain de grano tiene el nombre cartdel tipo de grano . Cada grano solo puede tener un nombre de tipo de grano.

Para los granos genéricos, incluya la aridad genérica en el nombre del tipo de grano. Por ejemplo, considere la siguiente DictionaryGrain<K, V> clase:

[GrainType("dict`2")]
public class DictionaryGrain<K, V> : IDictionaryGrain<K, V>
{
    // Add your grain implementation here
}

La clase de grano tiene dos parámetros genéricos, por lo tanto, se agrega una comilla invertida ` seguida de la aridad genérica, 2, al final del nombre del tipo de grano dict para crear el nombre del tipo de grano dict`2. Esto se especifica en el atributo de la clase de grano: [GrainType("dict2")]'.

Llaves de cereales

Para mayor comodidad, Orleans expone métodos que permiten la construcción de claves de grano a partir de un Guid o Int64, además de un String. La clave principal está limitada al tipo de grano. Por lo tanto, la identidad completa de un grano se forma a partir de su tipo y llave.

El solicitante del proceso decide qué esquema usar. Las opciones son:

Dado que los datos subyacentes son los mismos, los esquemas se pueden usar indistintamente: todos están codificados como cadenas.

Las situaciones que requieren una instancia de grano singleton pueden usar un valor fijo conocido, como "default". Esto es simplemente una convención, pero la adhesión a ella aclara en el sitio del autor de la llamada que un grano singleton está en uso.

Uso de identificadores únicos globales (GUID) como claves

System.Guid crear claves útiles cuando se desea la aleatoriedad y la unicidad global, como al generar un nuevo trabajo en un sistema de procesamiento de trabajos. No es necesario coordinar la asignación de claves, ya que podría introducir un único punto de fallo o bloquear un recurso a nivel del sistema, creando potencialmente un cuello de botella. La posibilidad de colisiones de GUID es muy baja, por lo que es una opción común al diseñar sistemas que necesitan asignación aleatoria de identificadores.

Referenciar un grain por GUID en el código del cliente:

var grain = grainFactory.GetGrain<IExample>(Guid.NewGuid());

Recuperación de la clave principal del código de grano:

public override Task OnActivateAsync()
{
    Guid primaryKey = this.GetPrimaryKey();
    return base.OnActivateAsync();
}

Uso de enteros como claves

También hay disponible un entero largo. Esto tiene sentido si el grano persiste en una base de datos relacional, donde a menudo se prefieren índices numéricos sobre GUID.

Hacer referencia a un grano por un entero largo en el código de cliente:

var grain = grainFactory.GetGrain<IExample>(1);

Recuperación de la clave principal del código de grano:

public override Task OnActivateAsync()
{
    long primaryKey = this.GetPrimaryKeyLong();
    return base.OnActivateAsync();
}

Uso de cadenas como claves

Una clave de cadena también está disponible.

Referenciar un grain por String en el código del cliente:

var grain = grainFactory.GetGrain<IExample>("myGrainKey");

Recuperación de la clave principal del código de grano:

public override Task OnActivateAsync()
{
    string primaryKey = this.GetPrimaryKeyString();
    return base.OnActivateAsync();
}

Uso de claves compuestas

Si el sistema no encaja bien con GUID o longs, opte por una clave principal compuesta. Esto permite usar una combinación de un GUID o un long y una cadena para hacer referencia a un grain.

Hereda la interfaz de IGrainWithGuidCompoundKey o IGrainWithIntegerCompoundKey de la siguiente manera:

public interface IExampleGrain : Orleans.IGrainWithIntegerCompoundKey
{
    Task Hello();
}

En el código de cliente, esto agrega un segundo argumento al IGrainFactory.GetGrain método en el generador de granos:

var grain = grainFactory.GetGrain<IExample>(0, "a string!", null);

Para acceder a la clave compuesta en el grano, llame a una sobrecarga del método GetPrimaryKey (por ejemplo, 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 qué los granos usan identificadores lógicos?

En entornos orientados a objetos como .NET, la identidad de un objeto es difícil distinguir de una referencia a él. Cuando se crea un objeto mediante la new palabra clave , la referencia devuelta representa todos los aspectos de su identidad, excepto los que asignan el objeto a alguna entidad externa que representa. Orleans está diseñado para sistemas distribuidos. En los sistemas distribuidos, las referencias de objeto no pueden representar la identidad de instancia porque están limitadas al espacio de direcciones de un solo proceso. Orleans usa identificadores lógicos para evitar esta limitación. Los granos usan identificadores lógicos, por lo que las referencias de grano siguen siendo válidas en toda la duración del proceso y son portátiles de un proceso a otro. Esto les permite almacenarlos y recuperarlos más adelante, o enviarlos a través de una red a otro proceso de la aplicación, todo ello mientras siguen haciendo referencia a la misma entidad: el grano para el que se creó la referencia.