Training
Modul
Erstellen Ihrer ersten Orleans-App mit ASP.NET Core 8.0 - Training
Erfahren Sie, wie Sie cloudnative, verteilte Anwendungen mit Orleans erstellen.
Dieser Browser wird nicht mehr unterstützt.
Führen Sie ein Upgrade auf Microsoft Edge durch, um die neuesten Features, Sicherheitsupdates und den technischen Support zu nutzen.
In Orleans 7.0 wurden mehrere vorteilhafte Änderungen eingeführt, darunter Verbesserungen in den Bereichen Hosting, benutzerdefinierte Serialisierung, Unveränderlichkeit und Abstraktionen von Grains.
Bestehende Anwendungen, die Reminders, Streams oder Persistenz von Grains verwenden, können aufgrund von Änderungen in der Art und Weise, wie Orleans Grains und Streams identifiziert, nicht einfach zu Orleans 7.0 migriert werden. Wir planen, einen Migrationspfad für diese Anwendungen schrittweise anzubieten.
Anwendungen, die mit früheren Versionen von Orleans arbeiten, können nicht problemlos über ein paralleles Upgrade auf Orleans 7.0 aktualisiert werden. Daher muss eine andere Upgradestrategie verfolgt werden, z. B. die Bereitstellung eines neuen Clusters und Außerbetriebnahme des vorherigen Clusters. Orleans 7.0 ändert das Wire-Protokoll auf inkompatible Weise, d. h. Cluster können keine Kombination aus Orleans 7.0-Hosts und Hosts mit früheren Versionen von Orleans enthalten.
Wir haben solche Breaking Changes viele Jahre vermieden, sogar in allen Hauptversionen, warum jetzt? Es gibt zwei Hauptgründe: Identitäten und Serialisierung. In Bezug auf Identitäten bestehen Grain- und Streamidentitäten jetzt aus Zeichenfolgen, sodass Grains generische Typinformationen ordnungsgemäß codieren und Streams einfacher der Anwendungsdomäne zugeordnet werden können. Graintypen wurden zuvor anhand einer komplexen Datenstruktur identifiziert, die keine generischen Grains abbilden konnte, was zu Problemfällen führte. Streams wurden anhand des Namespace string
und des Schlüssel Guid identifiziert, was es Entwicklern erschwerte, eine Zuordnung zu ihrer Anwendungsdomäne vorzunehmen, auch wenn dies effizient war. Die Serialisierung ist jetzt versionstolerant, d. h. Sie können Ihre Typen auf bestimmte kompatible Weise ändern, indem Sie eine Reihe von Regeln befolgen, und sicher sein, dass Sie Ihre Anwendung ohne Serialisierungsfehler aktualisieren können. Dies war besonders problematisch, wenn Anwendungstypen in Streams oder Grainspeicher dauerhaft gespeichert wurden. In den folgenden Abschnitten werden die wichtigsten Änderungen ausführlich beschrieben und erläutert.
Wenn Sie für ein Projekt ein Upgrade auf Orleans 7.0 vornehmen, müssen Sie die folgenden Aktionen ausführen:
Microsoft.Orleans.CodeGenerator.MSBuild
und Microsoft.Orleans.OrleansCodeGenerator.Build
.
KnownAssembly
durch GenerateCodeForDeclaringAssemblyAttribute.Microsoft.Orleans.Sdk
-Paket verweist auf das C#-Quellcodegeneratorpaket (Microsoft.Orleans.CodeGenerator
).Microsoft.Orleans.OrleansRuntime
.
Microsoft.Orleans.Runtime
.ConfigureApplicationParts
.
Teile der Anwendung wurden entfernt. Der C#-Quellcodegenerator für Orleans wurde allen Paketen (einschließlich Client und Server) hinzugefügt und generiert automatisch das Äquivalent von Teilen der Anwendung.Microsoft.Orleans.OrleansServiceBus
durch Microsoft.Orleans.Streaming.EventHubs.Tipp
Für alle Orleans-Beispiele ist ein Upgrade auf Orleans 7.0 erfolgt. Sie können sie als Referenz für die vorgenommenen Änderungen verwenden. Weitere Informationen finden Sie unter Orleans-Issue 8035, in dem die Änderungen aufgeführt sind, die an den einzelnen Beispielen vorgenommen wurden.
Alle Orleans-Projekte verweisen entweder direkt oder indirekt auf das NuGet-Paket Microsoft.Orleans.Sdk
. Wenn ein Orleans-Projekt so konfiguriert ist, dass implizite Usings-Elemente (z. B. <ImplicitUsings>enable</ImplicitUsings>
) aktiviert sind, werden die Namespaces Orleans
und Orleans.Hosting
beide implizit verwendet. Dies bedeutet, dass Ihr App-Code diese Anweisungen nicht benötigt.
Weitere Informationen finden Sie unter ImplicitUsings und dotnet/orleans/src/Orleans.Sdk/build/Microsoft.Orleans.Sdk.targets.
Der Typ ClientBuilder wurde durch die Erweiterungsmethode UseOrleansClient für IHostBuilder ersetzt. Der Typ IHostBuilder
stammt aus dem NuGet-Paket Microsoft.Extensions.Hosting. Das bedeutet, dass Sie einen Orleans-Client einem vorhandenen Host hinzufügen können, ohne einen separaten Dependency Injection-Container erstellen zu müssen. Der Client stellt während des Startvorgangs eine Verbindung mit dem Cluster her. Nach Abschluss des Vorgangs IHost.StartAsync wird der Client automatisch verbunden. Zu IHostBuilder
hinzugefügte Dienste werden in der Reihenfolge ihrer Registrierung gestartet. Wenn Sie also UseOrleansClient
vor ConfigureWebHostDefaults aufrufen, wird Orleans beispielsweise vor dem Start von ASP.NET Core gestartet, sodass Sie in Ihrer ASP.NET Core-Anwendung sofort auf den Client zugreifen können.
Wenn Sie das vorherige ClientBuilder
-Verhalten emulieren möchten, können Sie ein separates HostBuilder
-Element erstellen und mit einem Orleans-Client konfigurieren. Für IHostBuilder
kann entweder ein Orleans-Client oder Orleans-Silo konfiguriert sein. Alle Silos registrieren eine Instanz von IGrainFactory und IClusterClient, die die Anwendung verwenden kann, sodass das separate Konfigurieren eines Clients unnötig ist und nicht unterstützt wird.
Orleans ermöglicht Grains während der Aktivierung und Deaktivierung die Ausführung von Code. Dies dient für Aufgaben wie das Lesen des Status aus dem Speicher oder das Protokollieren von Lebenszyklusnachrichten. In Orleans 7.0 hat sich die Signatur dieser Lebenszyklusmethoden geändert:
CancellationToken
. DeactivationReason
gibt an, warum die Aktivierung deaktiviert wurde. Von Entwicklern wird erwartet, dass sie diese Informationen für Protokollierungs- und Diagnosezwecke verwenden. Wenn CancellationToken
abgebrochen wird, muss der Deaktivierungsprozess umgehend abgeschlossen werden. Beachten Sie, dass Hosts jederzeit ausfallen können. Es ist daher nicht empfehlenswert, sich auf OnDeactivateAsync
zu verlassen, wenn es um wichtige Aktionen wie die Aufrechterhaltung kritischer Zustände geht.Betrachten Sie das folgende Beispiel eines Grains, das diese neuen Methoden überschreibt:
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;
}
Grains in Orleans müssen nicht mehr von der Basisklasse Grain oder einer anderen Klasse erben. Diese Funktionalität wird als POCO-Grains bezeichnet. So greifen Sie auf eine beliebige der folgenden Erweiterungsmethoden zu:
Ihr Grain muss entweder IGrainBase implementieren oder von Grain erben. Hier sehen Sie ein Beispiel der Implementierung von IGrainBase
für eine Grain-Klasse:
public sealed class PingGrain : IGrainBase, IPingGrain
{
public PingGrain(IGrainContext context) => GrainContext = context;
public IGrainContext GrainContext { get; }
public ValueTask Ping() => ValueTask.CompletedTask;
}
IGrainBase
definiert außerdem OnActivateAsync
und OnDeactivateAsync
mit Standardimplementierungen, sodass Ihr Grain nach Wunsch am Lebenszyklus teilnehmen kann:
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;
}
Die aufwändigste Änderung in Orleans 7.0 ist die Einführung des versionstoleranten Serialisierungsmoduls. Diese Änderung ist erfolgt, weil Anwendungen sich häufig weiterentwickeln. Dies war ein erheblicher Stolperstein für Entwickler, da das vorherige Serialisierungsmodul das Hinzufügen von Eigenschaften zu vorhandenen Typen nicht tolerieren konnte. Andererseits war das Serialisierungsmodul flexibel und ermöglichte es Entwicklern, die meisten .NET-Typen ohne Änderungen abzubilden, einschließlich Features wie Generics, Polymorphismus und Nachverfolgung von Verweisen. Ein Ersatz war längst überfällig, aber Benutzer benötigen weiterhin ein originalgetreues Abbilden ihrer Typen. Daher wurde in Orleans 7.0 ein Ersatzserialisierungsmodul eingeführt, das das originalgetreue Abbilden von .NET-Typen unterstützt und gleichzeitig die Weiterentwicklung von Typen zulässt. Das neue Serialisierungsmodul ist wesentlich effizienter als das vorherige, was durchgängig zu einem bis zu 170 % höheren Durchsatz führt.
Weitere Informationen finden Sie in den folgenden Artikeln zu Orleans 7.0:
Grains haben jeweils eine eindeutige Identität, die aus dem Typ und Schlüssel des Grains besteht. In früheren Versionen von Orleans wurde ein zusammengesetzter Typ für GrainId
-Elemente verwendet, um die folgenden Grainschlüssel zu unterstützen:
Dies ist mit einer gewissen Komplexität verbunden, wenn es um den Umgang mit Grainschlüsseln geht. Identitäten von Grains bestehen aus zwei Komponenten: Typ und Schlüssel. Die Typkomponente bestand zuvor aus einem numerischen Typcode, einer Kategorie und drei Bytes mit generischen Typinformationen.
Identitäten von Grains haben nun die Form type/key
, wobei type
und key
Zeichenfolgen sind. Die am häufigsten verwendete Grainschlüsselschnittstelle ist IGrainWithStringKey. Sie vereinfacht die Funktionsweise der Grainidentität erheblich und verbessert die Unterstützung generischer Graintypen.
Grainschnittstellen werden jetzt auch durch einen von Menschen lesbaren Namen dargestellt und nicht mehr durch eine Kombination aus einem Hashcode und einer Zeichenfolge, die alle generischen Typparameter abbildet.
Das neue System ist besser anpassbar, und diese Anpassungen lassen sich durch Attribute steuern.
class
gibt den Teil mit dem Typ der Grain-ID an.interface
gibt den Typ des Grains an, den IGrainFactory beim Abrufen eines Grainverweises standardmäßig auflösen soll. Wenn Sie z. B. IGrainFactory.GetGrain<IMyGrain>("my-key")
aufrufen, gibt die Grainfactory einen Verweis auf das Grain "my-type/my-key"
zurück, wenn für IMyGrain
das oben genannte Attribut angegeben wurde.Wie bereits erwähnt, können Sie die Standardnamen der Grainklassen und -schnittstellen für Ihre Typen überschreiben und so die zugrunde liegenden Typen umbenennen, ohne die Kompatibilität mit vorhandenen Bereitstellungen zu beeinträchtigen.
Als Orleans-Streams erstmals veröffentlicht wurden, konnten Streams nur mithilfe von Guid identifiziert werden. Dies war effizient, was die Arbeitsspeicherzuteilung betraf, aber es war für Benutzer schwierig, sinnvolle Streamidentitäten zu erstellen. Oftmals war eine Codierung oder Umleitung erforderlich, um die geeignete Streamidentität für einen bestimmten Zweck zu bestimmen.
In Orleans 7.0 werden Streams jetzt mithilfe von Zeichenfolgen identifiziert. Orleans.Runtime.StreamId struct
enthält drei Eigenschaften: StreamId.Namespace, StreamId.Key und StreamId.FullKey. Bei diesen Eigenschaftswerten handelt es sich um codierte UTF-8-Zeichenfolgen. Beispiel: StreamId.Create(String, String).
SimpleMessageStreams
(auch SMS genannt) wurde in Version 7.0 entfernt. SimpleMessageStreams verfügte über dieselbe Schnittstelle wie Orleans.Providers.Streams.PersistentStreams, verhielt sich aber ganz anders, da es auf direkte Aufrufe von Grain zu Grain angewiesen war. Um Verwirrung zu vermeiden, wurde SimpleMessageStreams entfernt und ein neuer Ersatz namens Orleans.BroadcastChannel eingeführt.
BroadcastChannel
unterstützt nur implizite Abonnements und kann in diesem Fall ein direkter Ersatz sein. Wenn Sie explizite Abonnements benötigen oder die PersistentStream
-Schnittstelle verwenden müssen (beispielsweise, wenn Sie SimpleMessageStreams in Tests verwendet haben, während EventHub
in der Produktion eingesetzt wurde), dann ist MemoryStream
die beste Wahl für Sie.
BroadcastChannel
verhält sich genauso wie SimpleMessageStreams, während MemoryStream
sich wie andere Streamanbieter verhält. Betrachten Sie das folgende Beispiel für die Verwendung von BroadcastChannel:
// 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;
}
}
}
Die Migration zu MemoryStream
ist einfacher, da nur die Konfiguration geändert werden muss. Beachten Sie die folgende Konfiguration von MemoryStream
:
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);
});
Das Telemetriesystem wurde in Orleans 7.0 aktualisiert und das vorherige System zugunsten standardisierter .NET-APIs wie .NET Metrics für Metriken und ActivitySource für Ablaufverfolgung entfernt.
In diesem Zusammenhang wurden die vorhandenen Microsoft.Orleans.TelemetryConsumers.*
-Pakete entfernt. Wir erwägen die Einführung einer neuen Reihe von Paketen, um den Prozess der Integration der von Orleans ausgegebenen Metriken in die von Ihnen gewählte Überwachungslösung zu vereinfachen. Wie immer sind Feedback und Beiträge willkommen.
Das Tool dotnet-counters
bietet eine Leistungsüberwachung zur Ad-hoc-Überwachung der Integrität und zur Leistungsuntersuchung auf erster Ebene. Für Orleans-Zähler kann das Tool dotnet-counters verwendet werden, um sie zu überwachen:
dotnet counters monitor -n MyApp --counters Microsoft.Orleans
In ähnlicher Weise können OpenTelemetry-Metriken Microsoft.Orleans
-Messungen hinzufügen, wie im folgenden Code gezeigt:
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics
.AddPrometheusExporter()
.AddMeter("Microsoft.Orleans"));
Um eine verteilte Ablaufverfolgung zu aktivieren, konfigurieren Sie OpenTelemetry wie im folgenden Code gezeigt:
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");
});
});
Im vorherigen Code ist OpenTelemetry für die Überwachung der folgenden Elemente konfiguriert:
Microsoft.Orleans.Runtime
Microsoft.Orleans.Application
Rufen Sie zum Weitergeben der Aktivität AddActivityPropagation auf:
builder.Host.UseOrleans((_, clientBuilder) =>
{
clientBuilder.AddActivityPropagation();
});
In Orleans 7.0 haben wir uns bemüht, Erweiterungen in separate Pakete umzugestalten, die nicht auf Orleans.Core angewiesen sind. Genauer gesagt, wurden Orleans.Streaming, Orleans.Reminders und Orleans.Transactions vom Kern getrennt. Das bedeutet, dass Sie bei diesen Paketen ausschließlich für das zahlen, was Sie nutzen, und kein Code im Kern von Orleans für diese Features dediziert ist. Dadurch werden die API-Oberfläche des Kerns und die Größe der Assembly verschlankt, der Kern vereinfacht und die Leistung verbessert. Was die Leistung betrifft, so erforderten Transaktionen in Orleans bisher Code, der für jede Methode ausgeführt wurde, um mögliche Transaktionen zu koordinieren. Dies wurde inzwischen auf methodenbezogen umgestellt.
Dies ist ein Breaking Change bei der Kompilierung. Möglicherweise haben Sie vorhandenen Code, der mit Erinnerungen oder Streams interagiert, indem er Methoden aufruft, die zuvor in der Basisklasse Grain definiert waren, jetzt aber Erweiterungsmethoden sind. Solche Aufrufe, die nicht this
angeben (z. B. GetReminders), müssen so geändert werden, dass sie this
enthalten (z. B. this.GetReminders()
), da Erweiterungsmethoden qualifiziert werden müssen. Wenn Sie diese Aufrufe nicht ändern, kommt es zu einem Kompilierungsfehler, und die erforderliche Codeänderung ist möglicherweise nicht offensichtlich, wenn Sie nicht wissen, was sich geändert hat.
In Orleans 7.0 wurde mit Orleans.ITransactionClient eine neue Abstraktion zur Koordinierung von Transaktionen eingeführt. Bisher konnten Transaktionen nur durch Grains koordiniert werden. Mit ITransactionClient
, das über Dependency Injection verfügbar ist, können Clients auch Transaktionen koordinieren, ohne dass ein zwischengeschaltetes Grain erforderlich ist. Im folgenden Beispiel wird innerhalb einer einzigen Transaktion Guthaben von einem Konto abgehoben und auf ein anderes eingezahlt. Dieser Code kann aus einem Grain heraus oder von einem externen Client aufgerufen werden, der ITransactionClient
aus dem Dependency Injection-Container abgerufen hat.
await transactionClient.RunTransaction(
TransactionOption.Create,
() => Task.WhenAll(from.Withdraw(100), to.Deposit(100)));
Für vom Client koordinierte Transaktionen muss der Client die erforderlichen Dienste zur Konfigurationszeit hinzufügen:
clientBuilder.UseTransactions();
Das Beispiel BankAccount veranschaulicht die Verwendung von ITransactionClient
. Weitere Informationen finden Sie unter Orleans-Transaktionen.
Grains sind standardmäßig Singlethread und verarbeiten die Anforderungen nacheinander von Anfang bis Ende. Mit anderen Worten: Grains sind standardmäßig eintrittsinvariant. Durch das Hinzufügen von ReentrantAttribute zu einer Grainklasse können mehrere Anforderungen gleichzeitig verarbeitet werden, und zwar auf geschachtelte Art und Weise, während sie immer noch Singlethread sind. Dies kann für Grains nützlich sein, die keinen internen Zustand enthalten oder viele asynchrone Vorgänge durchführen, wie z. B. HTTP-Aufrufe oder das Schreiben in eine Datenbank. Besondere Aufmerksamkeit ist geboten, wenn Anforderungen ineinander geschachtelt sein könnten. Es ist möglich, dass der Zustand eines Grains beobachtet wird, bevor eine await
-Anweisung sich geändert hat, wenn der asynchrone Vorgang abgeschlossen ist und die Methode die Ausführung fortsetzt.
Das folgende Grain stellt beispielsweise einen Zähler dar. Es wurde mit Reentrant
markiert, sodass mehrere Aufrufe ineinander geschachtelt sein dürfen. Die Increment()
-Methode sollte den internen Zähler erhöhen und den beobachteten Wert zurückgeben. Da der Körper der Increment()
-Methode jedoch den Status des Grains vor einem await
-Punkt beobachtet und danach aktualisiert, ist es möglich, dass mehrere ineinander geschachtelte Ausführungen von Increment()
zu einem _value
kleiner als die Gesamtanzahl der empfangenen Aufrufe von Increment()
führen können. Dies ist ein Fehler, der durch unsachgemäße Verwendung von Eintrittsinvarianz verursacht wurde.
Zum Beheben des Problems reicht das Entfernen von ReentrantAttribute.
[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;
}
}
Um solche Fehler zu verhindern, sind Grains standardmäßig nicht eintrittsinvariant. Der Nachteil dabei ist ein verringerter Durchsatz für Grains, die in ihrer Implementierung asynchrone Vorgänge durchführen, da andere Anforderungen nicht verarbeitet werden können, während das Grain auf den Abschluss eines asynchronen Vorgangs wartet. Um dieses Problem zu lösen, bietet Orleans mehrere Optionen, um in bestimmten Fällen Eintrittsinvarianz zu ermöglichen:
ReadOnly
-Anforderungen an diese Methode können von jeder anderen ReadOnly
-Anforderung ineinander geschachtelt werden. In diesem Sinne handelt es sich um eine eingeschränktere Form von AlwaysInterleave
.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;
Eintrittsinvarianz der Aufrufkette muss pro Grain und pro Aufrufkette aktiviert werden. Nehmen wir zum Beispiel zwei Grains: Grain A und Grain B. Wenn Grain A Eintrittsinvarianz der Aufrufkette aktiviert, ehe Grain B aufgerufen wird, kann Grain B bei diesem Aufruf einen Rückruf an Grain A tätigen. Grain A kann jedoch nicht in Grain B zurückgerufen werden, wenn für Grain B nicht auch Eintrittsinvarianz der Aufrufkette aktiviert ist. Dies muss pro Grain und pro Aufrufkette erfolgen.
Mit using var _ = RequestContext.SuppressCallChainReentrancy()
können Grains auch unterdrücken, dass Informationen über Eintrittsinvarianz der Aufrufkette nach unten gelangen. Dies verhindert den Wiedereintritt nachfolgender Anrufe.
Um Aufwärtskompatibilität mit Orleans-Clustering, Persistenz und Reminders sicherzustellen, die auf ADO.NET basieren, benötigen Sie das entsprechende SQL-Migrationsskript:
Wählen Sie die Dateien für die verwendete Datenbank aus, und wenden Sie sie der Reihe nach an.
Feedback zu .NET
.NET ist ein Open Source-Projekt. Wählen Sie einen Link aus, um Feedback zu geben:
Training
Modul
Erstellen Ihrer ersten Orleans-App mit ASP.NET Core 8.0 - Training
Erfahren Sie, wie Sie cloudnative, verteilte Anwendungen mit Orleans erstellen.