Tożsamość ziarna

Ziarna w każdym z Orleans nich mają jeden, unikatowy, zdefiniowany przez użytkownika identyfikator, który składa się z dwóch części:

  1. Nazwa typu ziarna, która jednoznacznie identyfikuje klasę ziarna.
  2. Klucz ziarna, który jednoznacznie identyfikuje logiczne wystąpienie tej klasy ziarna.

Typ ziarna i klucz są reprezentowane jako ciągi czytelne dla człowieka w i Orleans zgodnie z konwencją tożsamość ziarna jest zapisywana z typem ziarna i kluczem oddzielonym znakiem / . Na przykład shoppingcart/bob65 reprezentuje typ ziarna o nazwie shoppingcart z kluczem bob65.

Bezpośrednie konstruowanie tożsamości ziarna nie jest powszechne. Zamiast tego częściej tworzy się odwołania do ziarna przy użyciu polecenia Orleans.IGrainFactory.

W poniższych sekcjach omówiono bardziej szczegółowo nazwy typów ziarna i klucze ziarna.

Nazwy typów ziarna

Orleans Tworzy nazwę typu ziarna na podstawie klasy implementacji ziarna, usuwając sufiks "Grain" z nazwy klasy, jeśli jest obecny, i konwertując wynikowy ciąg na jego reprezentację małych liter. Na przykład klasa o nazwie ShoppingCartGrain będzie mieć nazwę shoppingcarttypu ziarna . Zaleca się, aby nazwy typów ziarna i klucze składały się tylko z znaków drukowalnych, takich jak znaki alfanumeryczne (a-z,ZA- i ) i-09 symbole, takie jak -, , _, @, . = Inne znaki mogą być obsługiwane lub nie są obsługiwane i często wymagają specjalnego traktowania podczas drukowania w dziennikach lub wyświetlania jako identyfikatory w innych systemach, takich jak bazy danych.

Alternatywnie Orleans.GrainTypeAttribute atrybut może służyć do dostosowywania nazwy typu ziarna dla klasy ziarna, do której jest dołączony, jak w poniższym przykładzie:

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

W poprzednim przykładzie klasa ShoppingCartGrain ziarna ma nazwę carttypu ziarna . Każde ziarno może mieć tylko jedną nazwę typu ziarna.

W przypadku ziarna ogólnego należy uwzględnić rodzajową arity w nazwie typu ziarna. Rozważmy na przykład następującą DictionaryGrain<K, V> klasę:

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

Klasa ziarna ma dwa ogólne parametry, więc backtick`, po którym następuje ogólna arity, 2, jest dodawany na końcu nazwy typu ziarna, aby utworzyć nazwę dict`2typu ziarna , dict jak określono w atrybucie w klasie ziarna, [GrainType("dict`2")].

Klucze ziarna

Dla wygody, uwidacznia metody, Orleans które umożliwiają konstruowanie kluczy ziarna z elementu Guid lub Int64, oprócz Stringelementu . Klucz podstawowy ma zakres do typu ziarna. W związku z tym kompletna tożsamość ziarna jest tworzona z typu ziarna i jego klucza.

Obiekt wywołujący ziarna decyduje, który schemat ma być używany. Dostępne opcje:

Ponieważ dane bazowe są takie same, schematy mogą być używane zamiennie: wszystkie są kodowane jako ciągi.

Sytuacje wymagające wystąpienia pojedynczego ziarna mogą używać dobrze znanej stałej wartości, takiej jak "default". Jest to tylko konwencja, ale przestrzegając tej konwencji, staje się jasne w miejscu rozmówcy, że jednotonowe ziarno jest używane.

Używanie unikatowych identyfikatorów globalnych (GUID) jako kluczy

System.Guid umożliwia tworzenie przydatnych kluczy, gdy wymagana jest losowość i globalna unikatowość, na przykład podczas tworzenia nowego zadania w systemie przetwarzania zadań. Nie musisz koordynować alokacji kluczy, co może powodować pojedynczy punkt awarii w systemie lub blokadę po stronie systemu na zasobie, który może stanowić wąskie gardło. Istnieje bardzo niskie prawdopodobieństwo kolizji identyfikatorów GUID, więc są one typowym wyborem podczas tworzenia architektury systemu, który musi przydzielić losowe identyfikatory.

Odwoływanie się do ziarna według identyfikatora GUID w kodzie klienta:

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

Pobieranie klucza podstawowego z kodu ziarna:

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

Używanie liczb całkowitych jako kluczy

Dostępna jest również długa liczba całkowita, co miałoby sens, jeśli ziarno jest utrwalane w relacyjnej bazie danych, gdzie indeksy liczbowe są preferowane przez identyfikatory GUID.

Odwoływanie się do ziarna według długiej liczby całkowitej w kodzie klienta:

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

Pobieranie klucza podstawowego z kodu ziarna:

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

Używanie ciągów jako kluczy

Dostępny jest również ciąg.

Odwoływanie się do ziarna według ciągu w kodzie klienta:

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

Pobieranie klucza podstawowego z kodu ziarna:

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

Używanie kluczy złożonych

Jeśli masz system, który nie pasuje dobrze do identyfikatorów GUID lub długich, możesz wybrać złożony klucz podstawowy, który pozwala użyć kombinacji identyfikatora GUID lub długiego i ciągu odwołującego się do ziarna.

Interfejs można dziedziczyć z IGrainWithGuidCompoundKey interfejsu lub IGrainWithIntegerCompoundKey w następujący sposób:

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

W kodzie klienta spowoduje to dodanie drugiego argumentu IGrainFactory.GetGrain do metody w fabryce ziarna:

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

Aby uzyskać dostęp do klucza złożonego w ziarnie, możemy wywołać przeciążenie metody GrainExtensions.GetPrimaryKey ():GrainExtensions.GetPrimaryKeyLong

public class ExampleGrain : Orleans.Grain, IExampleGrain
{
    public Task Hello()
    {
        long primaryKey = this.GetPrimaryKeyLong(out string keyExtension);
        Console.WriteLine($"Hello from {keyExtension}");

        Task.CompletedTask;
    }
}

Dlaczego ziarna używają identyfikatorów logicznych

W środowiskach zorientowanych na obiekty, takich jak .NET, tożsamość obiektu jest trudna do odróżnienia od odwołania do niego. Po utworzeniu obiektu przy użyciu słowa kluczowego new odwołanie zwraca wszystkie aspekty jego tożsamości, z wyjątkiem tych, które mapują obiekt na jakąś jednostkę zewnętrzną, którą reprezentuje. Orleans jest przeznaczony dla systemów rozproszonych. W systemach rozproszonych odwołania do obiektów nie mogą reprezentować tożsamości wystąpienia, ponieważ odwołania do obiektów są ograniczone do przestrzeni adresowej pojedynczego procesu. Orleans używa identyfikatorów logicznych, aby uniknąć tego ograniczenia. Ziarno używać identyfikatorów logicznych, aby odwołania ziarna pozostały prawidłowe w okresach istnienia procesu i są przenośne z jednego procesu do innego, co umożliwia ich przechowywanie i późniejsze pobieranie lub wysyłanie przez sieć do innego procesu w aplikacji, a jednocześnie odwołując się do tej samej jednostki: ziarna, dla którego utworzono odwołanie.