Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Orleans 7.0 wprowadza kilka korzystnych zmian, w tym ulepszenia hostingu, serializacji niestandardowej, niezmienności i abstrakcji ziarna.
Migracja
Ze względu na zmiany w sposobie Orleans identyfikowania ziarna i strumieni, migrowanie istniejących aplikacji przy użyciu przypomnień, strumieni lub trwałości ziarna do Orleans wersji 7.0 nie jest obecnie proste.
Bezproblemowe uaktualnianie aplikacji z poprzednimi Orleans wersjami za pośrednictwem uaktualnienia stopniowego do Orleans wersji 7.0 nie jest możliwe. W związku z tym należy użyć innej strategii uaktualniania, takiej jak wdrożenie nowego klastra i zlikwidowanie poprzedniego. Orleans 7.0 zmienia protokół komunikacyjny w sposób niekompatybilny, co oznacza, że klastry nie mogą zawierać mieszaniny hostów Orleans 7.0 i hostów z poprzednimi Orleans wersjami.
Takich poważnych zmian unikano przez wiele lat, nawet w głównych wydaniach. Dlaczego teraz? Istnieją dwie główne przyczyny: identyfikatory i serializacja. Tożsamości, w tym tożsamości typu ziaren i strumieni, składają się teraz z ciągów znaków. Dzięki temu ziarna mogą prawidłowo kodować ogólne informacje o typie i ułatwiają mapowanie strumieni do domeny aplikacji.
Orleans Wcześniej zidentyfikowano typy ziarna przy użyciu złożonej struktury danych, która nie może reprezentować ziarna ogólnego, co prowadzi do przypadków narożnych. Strumienie zostały zidentyfikowane za pomocą przestrzeni nazw string
oraz klucza Guid, co było wydajne, ale trudne do powiązania z domeną aplikacji. Serializacja jest teraz odporna na wersje. Oznacza to, że typy można modyfikować w określony zgodny sposób, zgodnie z zestawem reguł, z ufnością, że można uaktualnić aplikację bez błędów serializacji. Ta funkcja jest szczególnie przydatna, gdy typy aplikacji są utrwalane w strumieniach lub magazynie ziarna. W poniższych sekcjach szczegółowo omówiono główne zmiany i omówimy je dalej.
Zmiany w opakowaniach
Podczas uaktualniania projektu do Orleans wersji 7.0 wykonaj następujące czynności:
- Wszyscy klienci powinni odwoływać się do firmy Microsoft.Orleans. Klient.
- Wszystkie silosy (serwery) powinny odwoływać się do firmy Microsoft.Orleans Serwer.
- Wszystkie inne pakiety powinny odwoływać się do microsoft.Orleans. Zestaw SDK.
- Zarówno pakiety klienta, jak i serwera zawierają odwołanie do Microsoft.Orleans.Sdk.
- Usuń wszystkie odwołania do
Microsoft.Orleans.CodeGenerator.MSBuild
iMicrosoft.Orleans.OrleansCodeGenerator.Build
.- Zastąp użycia
KnownAssembly
GenerateCodeForDeclaringAssemblyAttribute. - Pakiet
Microsoft.Orleans.Sdk
odwołuje się do pakietu generatora źródła języka C# (Microsoft.Orleans.CodeGenerator
).
- Zastąp użycia
- Usuń wszystkie odwołania do
Microsoft.Orleans.OrleansRuntime
.-
Microsoft.Orleans. Pakiety serwerów odwołują się do jego zastąpienia,
Microsoft.Orleans.Runtime
.
-
Microsoft.Orleans. Pakiety serwerów odwołują się do jego zastąpienia,
- Usuń wywołania do
ConfigureApplicationParts
. Części aplikacji zostały usunięte. Generator źródła języka C# dla Orleans jest dodawany do wszystkich pakietów (w tym klienta i serwera) i automatycznie generuje odpowiednik części składowych aplikacji. - Zastąp odwołania do
Microsoft.Orleans.OrleansServiceBus
z Microsoft.Orleans.Streaming.EventHubs. - Jeśli używasz przypomnień, dodaj odwołanie do Microsoft.Orleans.Reminders.
- W przypadku korzystania ze strumieni dodaj odwołanie do Microsoft.Orleans.Streaming.
Wskazówka
Wszystkie próbki Orleans zostały uaktualnione do Orleans wersji 7.0 i mogą być używane jako odwołanie do wprowadzonych zmian. Aby uzyskać więcej informacji, zobacz Orleans kwestię nr 8035, który wyszczególnia zmiany wprowadzone w poszczególnych przykładach.
Orleans globalne dyrektywy dotyczące używania
Wszystkie Orleans projekty bezpośrednio lub pośrednio odwołują się do Microsoft.Orleans.Sdk
pakietu NuGet.
Orleans Gdy projekt jest skonfigurowany do włączenia niejawnych użyć (na przykład <ImplicitUsings>enable</ImplicitUsings>
), projekt niejawnie korzysta z obu przestrzeni nazw, takich jak Orleans
i Orleans.Hosting
. Oznacza to, że kod aplikacji nie potrzebuje tych using
dyrektyw.
Aby uzyskać więcej informacji, zobacz ImplicitUsings i dotnet/orleans/src/Orleans.Sdk/build/Microsoft.Orleans.Sdk.targets.
Hostowanie
Typ ClientBuilder jest zastępowany przez metodę rozszerzenia UseOrleansClient na IHostBuilder. Typ IHostBuilder
pochodzi z pakietu NuGet Microsoft.Extensions.Hosting . Oznacza to, że Orleans klient można dodać do istniejącego hosta bez tworzenia oddzielnego kontenera iniekcji zależności. Klient nawiązuje połączenie z klastrem podczas uruchamiania. Po IHost.StartAsync zakończeniu klient połączy się automatycznie. Usługi dodane do IHostBuilder
są uruchamiane w kolejności rejestracji. Wywołanie UseOrleansClient
przed wywołaniem ConfigureWebHostDefaults zapewnia na przykład, że Orleans rozpoczyna się przed rozpoczęciem ASP.NET Core, co umożliwia natychmiastowy dostęp do klienta z aplikacji ASP.NET Core.
Aby emulować poprzednie ClientBuilder
zachowanie, utwórz oddzielny HostBuilder
i skonfiguruj go za pomocą klienta Orleans. Element IHostBuilder
można skonfigurować albo za pomocą klienta Orleans, albo z użyciem silosu Orleans. Wszystkie silosy rejestrują wystąpienia IGrainFactory i IClusterClient, które aplikacja może używać, dlatego osobna konfiguracja klienta jest niepotrzebna i nieobsługiwana.
OnActivateAsync
i OnDeactivateAsync
zmiana podpisu
Orleans umożliwia ziarnom wykonywanie kodu podczas aktywacji i dezaktywacji. To polecenie umożliwia wykonywanie zadań, takich jak odczytywanie stanu z pamięci masowej oraz rejestrowanie wiadomości o cyklu życia. W Orleans wersji 7.0 sygnatury tych metod cyklu życia uległy zmianie.
- OnActivateAsync() teraz akceptuje CancellationToken parametr. Po anulowaniu CancellationToken porzuć proces aktywacji.
-
OnDeactivateAsync() Teraz akceptuje DeactivationReason parametr i
CancellationToken
parametr.DeactivationReason
wskazuje, dlaczego aktywacja jest dezaktywowana. Te informacje służą do rejestrowania i diagnostyki. Po anulowaniuCancellationToken
niezwłocznie zakończ proces dezaktywacji. Należy pamiętać, że ponieważ dowolny host może zawieść w dowolnym momencie, poleganie naOnDeactivateAsync
do wykonywania ważnych działań, takich jak utrwalanie stanu krytycznego, nie jest zalecane.
Rozważmy następujący przykład ziarna przesłaniającego te nowe metody:
public sealed class PingGrain : Grain, IPingGrain
{
private readonly ILogger<PingGrain> _logger;
public PingGrain(ILogger<PingGrain> logger) =>
_logger = logger;
public override Task OnActivateAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("OnActivateAsync()");
return Task.CompletedTask;
}
public override Task OnDeactivateAsync(DeactivationReason reason, CancellationToken token)
{
_logger.LogInformation("OnDeactivateAsync({Reason})", reason);
return Task.CompletedTask;
}
public ValueTask Ping() => ValueTask.CompletedTask;
}
Ziarna POCO i IGrainBase
Ziarna w Orleans nie muszą już dziedziczyć z klasy bazowej Grain ani jakiejkolwiek innej klasy. Ta funkcja jest określana jako ziarna POCO . Aby uzyskać dostęp do metod rozszerzeń, takich jak na przykład którakolwiek z następujących:
- DeactivateOnIdle
- AsReference
- Cast
- GetPrimaryKey
- GetReminder
- GetReminders
- RegisterOrUpdateReminder
- UnregisterReminder
- GetStreamProvider
Ziarno musi albo implementować IGrainBase, albo dziedziczyć po Grain. Oto przykład zastosowania IGrainBase
w klasie ziarna:
public sealed class PingGrain : IGrainBase, IPingGrain
{
public PingGrain(IGrainContext context) => GrainContext = context;
public IGrainContext GrainContext { get; }
public ValueTask Ping() => ValueTask.CompletedTask;
}
IGrainBase
Ponadto definiuje OnActivateAsync
i OnDeactivateAsync
z domyślnymi implementacjami, dzięki czemu ziarno może uczestniczyć w jego cyklu życia w razie potrzeby:
public sealed class PingGrain : IGrainBase, IPingGrain
{
private readonly ILogger<PingGrain> _logger;
public PingGrain(IGrainContext context, ILogger<PingGrain> logger)
{
_logger = logger;
GrainContext = context;
}
public IGrainContext GrainContext { get; }
public Task OnActivateAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("OnActivateAsync()");
return Task.CompletedTask;
}
public Task OnDeactivateAsync(DeactivationReason reason, CancellationToken token)
{
_logger.LogInformation("OnDeactivateAsync({Reason})", reason);
return Task.CompletedTask;
}
public ValueTask Ping() => ValueTask.CompletedTask;
}
Serializacja
Najbardziej uciążliwą zmianą w Orleans wersji 7.0 jest wprowadzenie serializatora odpornego na wersję. Ta zmiana została wprowadzona, ponieważ aplikacje mają tendencję do rozwoju, co doprowadziło do znacznej pułapki dla deweloperów, ponieważ poprzedni serializator nie mógł tolerować dodawania właściwości do istniejących typów. Z drugiej strony poprzedni serializator był elastyczny, umożliwiając reprezentację większości typów platformy .NET bez modyfikacji, w tym funkcje takie jak typy ogólne, polimorfizm i śledzenie odwołań. Wymiana od dawna była konieczna, ale nadal potrzebna jest reprezentacja typów o wysokiej jakości. Orleans W związku z tym w wersji 7.0 wprowadzono zastępczy serializator obsługujący reprezentację wysokiej wierności typów platformy .NET, jednocześnie umożliwiając rozwój typów. Nowy serializator jest znacznie bardziej wydajny niż poprzedni, co skutkuje nawet o 170% wyższą całościową przepływnością.
Aby uzyskać więcej informacji, zobacz następujące artykuły dotyczące Orleans wersji 7.0:
Tożsamości ziarna
Ziarna mają unikatową tożsamość składającą się z typu ziarna i jego klucza. Poprzednie wersje Orleans używały typu złożonego dla GrainId
ów, aby obsługiwać klucze ziarna w jednym z następujących przypadków:
Takie podejście wiąże się z pewną złożonością podczas pracy z kluczami ziarna. Tożsamości ziaren składają się z dwóch elementów: typu i klucza. Składnik typu składał się wcześniej z kodu typu liczbowego, kategorii i 3 bajtów ogólnych informacji o typie.
Tożsamości ziarna mają teraz postać type/key
, gdzie zarówno type
, jak i key
są ciągami. Najczęściej używany interfejs klucza ziarna to IGrainWithStringKey. Znacznie upraszcza to mechanizm identyfikacji ziarna i ulepsza wsparcie dla typów ziarna ogólnego.
Interfejsy ziarna są teraz również reprezentowane przy użyciu nazwy czytelnej dla człowieka, a nie kombinacji kodu skrótu i reprezentacji ciągu dowolnych parametrów typu ogólnego.
Nowy system jest bardziej dostosowywalny, a te dostosowania mogą być sterowane atrybutami.
-
GrainTypeAttribute(String) na ziarnie
class
określa część Typ identyfikatora ziarna. -
DefaultGrainTypeAttribute(String) w ziarnie
interface
określa typ ziarna, który IGrainFactory powinien być rozpoznawany domyślnie podczas uzyskiwania odwołania ziarna. Na przykład, gdy wywoływana jest fabryka ziarnaIGrainFactory.GetGrain<IMyGrain>("my-key")
, zwraca ona odwołanie do ziarna"my-type/my-key"
, jeśliIMyGrain
ma wspomniany wcześniej atrybut. - GrainInterfaceTypeAttribute(String) umożliwia zastąpienie nazwy interfejsu. Jawne określenie nazwy przy użyciu tego mechanizmu umożliwia zmianę nazwy typu interfejsu bez przerywania zgodności z istniejącymi odwołaniami ziarna. Należy pamiętać, że interfejs powinien również mieć AliasAttribute w tym przypadku, ponieważ jego tożsamość może być serializowana. Aby uzyskać więcej informacji na temat określania aliasu typu, zobacz sekcję dotyczącą serializacji.
Jak wspomniano powyżej, zastąpienie domyślnych nazw klas ziarna i interfejsów dla typów umożliwia zmianę nazw typów bazowych bez przerywania zgodności z istniejącymi wdrożeniami.
Tożsamości strumienia
Po Orleans pierwszym udostępnieniu strumieni można było identyfikować strumienie tylko przy użyciu Guid. Takie podejście było wydajne pod względem alokacji pamięci, ale utrudniało tworzenie znaczących tożsamości strumienia, często wymagając kodowania lub pośredniego określenia odpowiedniej tożsamości strumienia w danym celu.
W Orleans wersji 7.0 strumienie są identyfikowane przy użyciu ciągów. Zawiera Orleans.Runtime.StreamIdstruct
trzy właściwości: StreamId.Namespace, StreamId.Keyi StreamId.FullKey. Te wartości właściwości są kodowane ciągami UTF-8. Na przykład zobacz StreamId.Create(String, String).
Zamiana SimpleMessageStreams na BroadcastChannel
SimpleMessageStreams
(nazywany również sms) jest usuwany w wersji 7.0. SMS miał ten sam interfejs co Orleans.Providers.Streams.PersistentStreams, ale jego zachowanie było zupełnie inne, ponieważ opierało się na bezpośrednich wywołaniach między ziarnami. Aby uniknąć nieporozumień, wiadomość SMS została usunięta i wprowadzono nową nazwę zastępczą Orleans.BroadcastChannel .
BroadcastChannel
Obsługuje tylko niejawne subskrypcje i może być bezpośrednim zastąpieniem w tym przypadku. Jeśli potrzebne są jawne subskrypcje lub konieczne jest użycie interfejsu PersistentStream
(na przykład, gdy program SMS wykorzystywano w testach, a EventHub
w środowisku produkcyjnym), MemoryStream
będzie najlepszym wyborem.
BroadcastChannel
działa tak samo jak SMS, podczas gdy MemoryStream
zachowuje się jak inni dostawcy usług strumieniowych. Rozważmy następujący przykład użycia kanału emisji:
// Configuration
builder.AddBroadcastChannel(
"my-provider",
options => options.FireAndForgetDelivery = false);
// Publishing
var grainKey = Guid.NewGuid().ToString("N");
var channelId = ChannelId.Create("some-namespace", grainKey);
var stream = provider.GetChannelWriter<int>(channelId);
await stream.Publish(1);
await stream.Publish(2);
await stream.Publish(3);
// Simple implicit subscriber example
[ImplicitChannelSubscription]
public sealed class SimpleSubscriberGrain : Grain, ISubscriberGrain, IOnBroadcastChannelSubscribed
{
// Called when a subscription is added to the grain
public Task OnSubscribed(IBroadcastChannelSubscription streamSubscription)
{
streamSubscription.Attach<int>(
item => OnPublished(streamSubscription.ChannelId, item),
ex => OnError(streamSubscription.ChannelId, ex));
return Task.CompletedTask;
// Called when an item is published to the channel
static Task OnPublished(ChannelId id, int item)
{
// Do something
return Task.CompletedTask;
}
// Called when an error occurs
static Task OnError(ChannelId id, Exception ex)
{
// Do something
return Task.CompletedTask;
}
}
}
Migracja do MemoryStream
jest łatwiejsza, ponieważ tylko konfiguracja wymaga zmiany. Rozważ następującą MemoryStream
konfigurację:
builder.AddMemoryStreams<DefaultMemoryMessageBodySerializer>(
"in-mem-provider",
_ =>
{
// Number of pulling agent to start.
// DO NOT CHANGE this value once deployed, if you do rolling deployment
_.ConfigurePartitioning(partitionCount: 8);
});
OpenTelemetry
System telemetrii jest aktualizowany w Orleans wersji 7.0, a poprzedni system jest usuwany na rzecz ustandaryzowanych interfejsów API platformy .NET, takich jak .NET Metrics do pomiaru metryk i ActivitySource do śledzenia.
W tym celu istniejące Microsoft.Orleans.TelemetryConsumers.*
pakiety są usuwane. Rozważany jest nowy zestaw pakietów, aby usprawnić integrację metryk, które są emitowane przez Orleans, do wybranego rozwiązania monitorowania. Jak zawsze, opinie i wkład są mile widziane.
Narzędzie dotnet-counters
oferuje monitorowanie wydajności na potrzeby monitorowania kondycji ad hoc i badania wydajności pierwszego poziomu. W przypadku Orleans liczników użyj narzędzia dotnet-counters , aby je monitorować:
dotnet counters monitor -n MyApp --counters Microsoft.Orleans
Podobnie dodaj mierniki Microsoft.Orleans
do metryk OpenTelemetry, jak pokazano w poniższym kodzie:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics
.AddPrometheusExporter()
.AddMeter("Microsoft.Orleans"));
Aby włączyć śledzenie rozproszone, skonfiguruj metodę OpenTelemetry, jak pokazano w poniższym kodzie:
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing.SetResourceBuilder(ResourceBuilder.CreateDefault()
.AddService(serviceName: "ExampleService", serviceVersion: "1.0"));
tracing.AddAspNetCoreInstrumentation();
tracing.AddSource("Microsoft.Orleans.Runtime");
tracing.AddSource("Microsoft.Orleans.Application");
tracing.AddZipkinExporter(options =>
{
options.Endpoint = new Uri("http://localhost:9411/api/v2/spans");
});
});
W poprzednim kodzie funkcja OpenTelemetry jest skonfigurowana do monitorowania:
Microsoft.Orleans.Runtime
Microsoft.Orleans.Application
Aby propagować działanie, wywołaj AddActivityPropagation:
builder.Host.UseOrleans((_, clientBuilder) =>
{
clientBuilder.AddActivityPropagation();
});
Refaktoryzacja funkcji z pakietu podstawowego do oddzielnych pakietów
W wersji 7.0 Orleans rozszerzenia zostały wyodrębnione do oddzielnych pakietów, które nie zależą od Orleans.Core. Mianowicie , Orleans.StreamingOrleans.Remindersi Orleans.Transactions zostały oddzielone od rdzenia. Oznacza to, że te pakiety są całkowicie opłacane za to, co jest używane, a żaden kod w rdzeniu Orleans nie jest przeznaczony dla tych funkcji. Takie podejście pozwala obniżyć rozmiar podstawowego interfejsu API i zestawu, uprościć rdzeń i zwiększyć wydajność. W odniesieniu do wydajności transakcje w Orleans poprzednio wymagały wykonania kodu dla każdej metody w celu koordynowania potencjalnych transakcji. Ta logika koordynacji jest teraz przenoszona do poszczególnych metod.
To jest zmiana łamiąca zgodność kompilacji. Istniejący kod współdziałający z przypomnieniami lub strumieniami przez wywołanie metod zdefiniowanych wcześniej w klasie bazowej Grain może spowodować przerwanie, ponieważ są to teraz metody rozszerzeń. Zaktualizuj takie wywołania, które nie określają this
(np. GetReminders), aby uwzględniały this
(np. this.GetReminders()
), ponieważ metody rozszerzeń muszą być kwalifikowane. Błąd kompilacji występuje, jeśli te wywołania nie są aktualizowane, a wymagana zmiana kodu może nie być oczywista bez znajomości tego, co się zmieniło.
Klient transakcji
Orleans 7.0 wprowadza nową abstrakcję do koordynowania transakcji: Orleans.ITransactionClient. Wcześniej tylko ziarna mogły koordynować transakcje. Dzięki ITransactionClient
, który jest dostępny za pośrednictwem wstrzykiwania zależności, klienci mogą koordynować transakcje bez potrzeby korzystania z pośrednictwa. Poniższy przykład wycofuje środki z jednego konta i deponuje je do innej w ramach jednej transakcji. Wywołaj ten kod z poziomu ziarna lub z klienta zewnętrznego, który pobrał element ITransactionClient
z kontenera do wstrzykiwania zależności.
await transactionClient.RunTransaction(
TransactionOption.Create,
() => Task.WhenAll(from.Withdraw(100), to.Deposit(100)));
W przypadku transakcji koordynowanych przez klienta klient musi dodać wymagane usługi podczas konfiguracji:
clientBuilder.UseTransactions();
W przykładzie BankAccount pokazano użycie obiektu ITransactionClient
. Aby uzyskać więcej informacji, zobacz Orleans transakcje.
Reentrancja łańcucha wywołań
Ziarna są domyślnie jednowątkowe i przetwarzają żądania pojedynczo od początku do końca. Innymi słowy, ziarna nie są z natury reentrantne. Dodanie ReentrantAttribute do klasy ziarna umożliwia ziarno przetwarzać wiele żądań równocześnie w sposób naprzemienny, przy jednoczesnym zachowaniu pracy w pojedynczym wątku. Ta funkcja może być przydatna dla ziaren, które nie mają stanu wewnętrznego lub wykonują wiele operacji asynchronicznych, takich jak wykonywanie wywołań HTTP lub zapisywanie w bazie danych. Wymagana jest dodatkowa ostrożność, gdy żądania mogą się nakładać: istnieje możliwość, że stan ziarna zaobserwowany przed wykonaniem instrukcji await
zmieni się do czasu zakończenia operacji asynchronicznej i wznowienia wykonywania metody.
Na przykład następujące ziarno reprezentuje licznik. Jest ona oznaczona jako Reentrant
, co umożliwia przeplatywanie wielu wywołań. Metoda Increment()
powinna zwiększać licznik wewnętrzny i zwracać obserwowaną wartość. Jednak ponieważ Increment()
treść metody obserwuje stan ziarna przed await
punktem i aktualizuje go później, wiele przeplatania wykonań Increment()
może spowodować _value
zmniejszenie całkowitej liczby Increment()
odebranych wywołań. Jest to błąd spowodowany niewłaściwym użyciem ponownego uruchamiania.
Usunięcie ReentrantAttribute wystarczy, aby rozwiązać ten problem.
[Reentrant]
public sealed class CounterGrain : Grain, ICounterGrain
{
int _value;
/// <summary>
/// Increments the grain's value and returns the previous value.
/// </summary>
public Task<int> Increment()
{
// Do not copy this code, it contains an error.
var currentVal = _value;
await Task.Delay(TimeSpan.FromMilliseconds(1_000));
_value = currentVal + 1;
return currentValue;
}
}
Aby zapobiec takim błędom, ziarna są domyślnie nieopakowalne. Minusem jest zmniejszenie przepływności dla ziaren wykonujących operacje asynchroniczne w ich implementacjach, ponieważ ziarna nie mogą przetwarzać innych żądań podczas oczekiwania na zakończenie operacji asynchronicznej. Aby to złagodzić, Orleans oferuje kilka opcji umożliwiających ponowny dostęp w niektórych przypadkach.
- W przypadku całej klasy: umieszczenie ReentrantAttribute obiektu na ziarno pozwala na przeplatanie dowolnego żądania do ziarna z dowolnym innym żądaniem.
- W przypadku podzbioru metod: umieszczenie metody AlwaysInterleaveAttribute na interfejsie ziarna pozwala żądaniom do tej metody przeplatać się z dowolnym innym żądaniem oraz umożliwia przeplatanie się innych żądań do tej metody.
- W przypadku podzestawu metod: umieszczenie ReadOnlyAttribute metody na interfejsie ziarna umożliwia wysyłanie żądań do tej metody w celu przeplatanie się z dowolnym innym
ReadOnly
ReadOnly
żądaniem i umożliwia innym żądaniom przeplatanie żądań do tej metody. W tym sensie jest to bardziej ograniczona formaAlwaysInterleave
. - W przypadku dowolnego żądania w łańcuchu wywołań: RequestContext.AllowCallChainReentrancy() i RequestContext.SuppressCallChainReentrancy() pozwalają na włączanie i wyłączanie możliwości ponownego wejścia żądań podrzędnych do ziarna. Oba wywołania zwracają wartość, która musi zostać usunięta podczas zamykania żądania. W związku z tym należy użyć ich w następujący sposób:
public Task<int> OuterCall(IMyGrain other)
{
// Allow call-chain reentrancy for this grain, for the duration of the method.
using var _ = RequestContext.AllowCallChainReentrancy();
await other.CallMeBack(this.AsReference<IMyGrain>());
}
public Task CallMeBack(IMyGrain grain)
{
// Because OuterCall allowed reentrancy back into that grain, this method
// will be able to call grain.InnerCall() without deadlocking.
await grain.InnerCall();
}
public Task InnerCall() => Task.CompletedTask;
Opcja włączenia rekurencji łańcucha wywołań dla każdego ziarna i każdego łańcucha wywołań. Rozważmy na przykład dwa obiekty, A i B. Jeśli obiekt A umożliwia ponowną reentywność łańcucha wywołań przed wywołaniem obiektu B, wtedy obiekt B może wywołać zwrotnie obiekt A w tym wywołaniu. Jednak ziarno A nie może wykonać wywołania zwrotnego do ziarna B, jeśli ziarno B nie również włączyło ponownego wywołania łańcucha wywołań. Jest włączane na poziomie każdego ziarna oraz każdego łańcucha wywołań.
Ziarna mogą również tłumić informacje o reentrantności łańcucha wywołań, aby nie przepływały w dół łańcucha wywołań przy użyciu using var _ = RequestContext.SuppressCallChainReentrancy()
. Uniemożliwia to ponowne wprowadzanie kolejnych wywołań.
skrypty migracji ADO.NET
Aby zapewnić zgodność z Orleans klastrowaniem, trwałością i przypomnieniami opartymi na ADO.NET, wymagany jest odpowiedni skrypt migracji SQL:
- Grupowanie
- Wytrwałość
- Przypomnienia
Wybierz pliki używanej bazy danych i zastosuj je w kolejności.