Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
Les grains peuvent avoir plusieurs objets de données persistants nommés associés. Ces objets d’état sont chargés à partir du stockage lors de l’activation du grain afin qu’ils soient disponibles lors des requêtes. La persistance des grains utilise un modèle de plug-in extensible, ce qui vous permet d’utiliser des fournisseurs de stockage pour n’importe quelle base de données. Ce modèle de persistance est conçu pour simplifier et n’est pas destiné à couvrir tous les modèles d’accès aux données. Les grains peuvent également accéder directement aux bases de données sans utiliser le modèle de persistance de grain.
Dans le diagramme précédent, UserGrain a un état profil et un état cart , chacun stocké dans un système de stockage distinct.
Objectifs
- Prendre en charge plusieurs objets de données persistants nommés par grain.
- Autorisez plusieurs fournisseurs de stockage configurés, chacun ayant potentiellement une configuration différente et soutenu par un système de stockage différent.
- Permettre à la communauté de développer et de publier des fournisseurs de stockage.
- Donnez aux fournisseurs de stockage un contrôle complet sur la façon dont ils stockent les données d’état des grains dans le magasin de stockage persistant. Corollary : Orleans ne fournit pas de solution de stockage ORM complète, mais permet aux fournisseurs de stockage personnalisés de prendre en charge des exigences ORM spécifiques en fonction des besoins.
Paquets
Vous trouverez Orleans des fournisseurs de stockage de grain sur NuGet. Les packages officiellement gérés sont les suivants :
- Microsoft.Orleans. Persistance.AdoNet : pour les bases de données SQL et d’autres systèmes de stockage pris en charge par ADO.NET. Pour plus d'informations, consultez persistance des grains ADO.NET.
- Microsoft.Orleans.Persistence.AzureStorage : Pour le stockage Azure, y compris le stockage Blob Azure et le stockage Table Azure (via l'API de stockage Table Azure). Pour plus d'informations, consultez la persistance des grains de stockage Azure.
- Microsoft.Orleans. Persistence.Cosmos : Fournisseur Azure Cosmos DB. Pour plus d’informations, consultez persistance des grains Azure Cosmos DB.
- Microsoft.Orleans. Persistance.DynamoDB : Pour Amazon DynamoDB. Pour plus d’informations, consultez persistance des grains Amazon DynamoDB.
- Microsoft.Orleans. Persistance.Redis : Pour Redis. Pour plus d’informations, consultez persistance des grains Redis.
API (Interface de Programmation d'Applications)
Les grains interagissent avec leur état persistant en utilisant IPersistentState<TState>, où TState est le type d’état sérialisable.
public interface IPersistentState<TState> : IStorage<TState>
{
}
public interface IStorage<TState> : IStorage
{
TState State { get; set; }
}
public interface IStorage
{
string Etag { get; }
bool RecordExists { get; }
Task ClearStateAsync();
Task WriteStateAsync();
Task ReadStateAsync();
}
public interface IPersistentState<TState> where TState : new()
{
TState State { get; set; }
string Etag { get; }
Task ClearStateAsync();
Task WriteStateAsync();
Task ReadStateAsync();
}
Orleans injecte des instances de IPersistentState<TState> dans le grain en tant que paramètres de constructeur. Vous pouvez annoter ces paramètres avec un PersistentStateAttribute attribut pour identifier le nom de l’état injecté et le nom du fournisseur de stockage qui l’a fourni. L’exemple suivant illustre cela en injectant deux états nommés dans le UserGrain constructeur :
public class UserGrain : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
private readonly IPersistentState<CartState> _cart;
public UserGrain(
[PersistentState("profile", "profileStore")] IPersistentState<ProfileState> profile,
[PersistentState("cart", "cartStore")] IPersistentState<CartState> cart)
{
_profile = profile;
_cart = cart;
}
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
}
Différents types de grain peuvent utiliser différents fournisseurs de stockage configurés, même si les deux sont du même type (par exemple, deux instances de fournisseur de stockage Table Azure différentes connectées à différents comptes de stockage Azure).
État de lecture
L'état du grain est automatiquement lu lorsque le grain s'active, mais il incombe aux grains de déclencher explicitement l'écriture pour tout état de grain modifié si nécessaire.
Si un grain souhaite lire explicitement son dernier état à partir du magasin de stockage, il doit appeler la ReadStateAsync méthode. Cela recharge l’état du grain à partir du magasin persistant via le fournisseur de stockage. La copie en mémoire précédente de l’état du grain est écrasée et remplacée lorsque l’opération Task de ReadStateAsync est terminée.
Accédez à la valeur de l’état à l’aide de la State propriété. Par exemple, la méthode suivante accède à l’état du profil déclaré dans le code ci-dessus :
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
Il n’est pas nécessaire d’appeler ReadStateAsync pendant l’opération normale ; Orleans charge automatiquement l’état lors de l’activation. Toutefois, vous pouvez utiliser ReadStateAsync pour actualiser l’état modifié en externe.
Consultez la section Modes d’échec ci-dessous pour plus d’informations sur les mécanismes de gestion des erreurs.
État d’écriture
Vous pouvez modifier l’état via la State propriété. L’état modifié n’est pas conservé automatiquement. Au lieu de cela, vous décidez quand conserver l’état en appelant la WriteStateAsync méthode. Par exemple, la méthode suivante met à jour une propriété sur State et persiste l'état mis à jour :
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
Conceptuellement, le Orleans runtime prend une copie approfondie de l’objet de données d’état du grain pour son utilisation pendant toutes les opérations d’écriture. Sous les couvertures, le runtime peut utiliser des règles d’optimisation et des heuristiques pour éviter d’effectuer une ou l’ensemble de la copie approfondie dans certaines circonstances, à condition que la sémantique d’isolation logique attendue soit conservée.
Consultez la section Modes d’échec ci-dessous pour plus d’informations sur les mécanismes de gestion des erreurs.
État clair
La méthode ClearStateAsync efface l’état du grain dans le stockage. Selon le fournisseur, cette opération peut éventuellement supprimer entièrement l’état du grain.
Commencez
Pour qu’un grain puisse utiliser la persistance, vous devez configurer un fournisseur de stockage sur le silo.
Tout d’abord, configurez des fournisseurs de stockage, un pour l’état du profil et un pour l’état du panier :
L’utilisation DefaultAzureCredential avec un point de terminaison d’URI est l’approche recommandée pour les environnements de production.
var tableEndpoint = new Uri(configuration["AZURE_TABLE_STORAGE_ENDPOINT"]!);
var blobEndpoint = new Uri(configuration["AZURE_BLOB_STORAGE_ENDPOINT"]!);
var credential = new DefaultAzureCredential();
var builder = Host.CreateApplicationBuilder();
builder.UseOrleans(siloBuilder =>
{
siloBuilder.AddAzureTableGrainStorage(
name: "profileStore",
configureOptions: options =>
{
options.TableServiceClient = new TableServiceClient(tableEndpoint, credential);
})
.AddAzureBlobGrainStorage(
name: "cartStore",
configureOptions: options =>
{
options.BlobServiceClient = new BlobServiceClient(blobEndpoint, credential);
});
});
using var host = builder.Build();
var host = new HostBuilder()
.UseOrleans(siloBuilder =>
{
siloBuilder.AddAzureTableGrainStorage(
name: "profileStore",
configureOptions: options =>
{
// Use JSON for serializing the state in storage
options.UseJson = true;
// Configure the storage connection key
options.ConnectionString =
"DefaultEndpointsProtocol=https;AccountName=data1;AccountKey=SOMETHING1";
})
.AddAzureBlobGrainStorage(
name: "cartStore",
configureOptions: options =>
{
// Use JSON for serializing the state in storage
options.UseJson = true;
// Configure the storage connection key
options.ConnectionString =
"DefaultEndpointsProtocol=https;AccountName=data2;AccountKey=SOMETHING2";
});
})
.Build();
Important
Microsoft vous recommande d’utiliser le flux d’authentification le plus sécurisé disponible. Si vous vous connectez à Azure SQL, les identités managées pour les ressources Azure sont la méthode d'authentification recommandée.
Maintenant que vous avez configuré un fournisseur de stockage nommé "profileStore", vous pouvez accéder à ce fournisseur à partir d’un grain.
Vous pouvez ajouter un état persistant à un grain de deux manières principales :
- En injectant IPersistentState<TState> dans le constructeur du grain.
- En héritant de Grain<TGrainState>.
La méthode recommandée pour ajouter du stockage à un grain consiste à injecter IPersistentState<TState> dans le constructeur d'un grain avec un attribut [PersistentState("stateName", "providerName")] associé. Pour plus d’informations sur Grain<TGrainState>, voir Using Grain<TGrainState> to add storage to a grain ci-dessous. L’utilisation Grain<TGrainState> est toujours prise en charge mais considérée comme une approche héritée.
Déclarez une classe destinée à contenir l’état de votre grain :
[Serializable]
public class ProfileState
{
public string Name { get; set; }
public Date DateOfBirth { get; set; }
}
Injectez IPersistentState<TState> dans le constructeur du grain :
public class UserGrainSimple : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
public UserGrainSimple(
[PersistentState("profile", "profileStore")]
IPersistentState<ProfileState> profile)
{
_profile = profile;
}
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
}
Important
L'état du profil ne sera pas chargé au moment où il est injecté dans le constructeur, rendant son accès invalide à ce moment-là. L’état sera chargé avant OnActivateAsync d’être appelé.
Maintenant que le grain a un état persistant, vous pouvez ajouter des méthodes pour lire et écrire l’état :
public class UserGrainComplete : Grain, IUserGrain
{
private readonly IPersistentState<ProfileState> _profile;
public UserGrainComplete(
[PersistentState("profile", "profileStore")]
IPersistentState<ProfileState> profile)
{
_profile = profile;
}
public Task<string> GetNameAsync() => Task.FromResult(_profile.State.Name);
public async Task SetNameAsync(string name)
{
_profile.State.Name = name;
await _profile.WriteStateAsync();
}
}
Modes d’échec pour les opérations de persistance
Modes d’échec pour les opérations de lecture
Les échecs retournés par le fournisseur de stockage pendant la lecture initiale des données d’état pour un grain particulier provoquent l’échec de l’opération d’activation pour ce grain. Dans ces cas, il n’y aura pas d’appel à cette méthode de rappel de cycle de vie de OnActivateAsync grain. La demande initiale au grain qui a provoqué les défauts d'activation retourne à l'appelant, comme toute autre défaillance lors de l'activation du grain. Les échecs rencontrés par le fournisseur de stockage lors de la lecture des données d’état pour un grain particulier entraînent une exception du ReadStateAsyncTask. Le grain peut choisir de gérer ou d’ignorer l’exception Task, comme n’importe quel autre Task dans Orleans.
Toute tentative d’envoi d’un message à un grain qui n’a pas pu être chargé au démarrage du silo en raison d’une configuration de fournisseur de stockage manquante ou incorrecte retourne l’erreur BadProviderConfigExceptionpermanente.
Modes d’échec pour les opérations d’écriture
Les échecs rencontrés par le fournisseur de stockage lors de l’écriture de données d’état pour un grain particulier entraînent une exception levée par le WriteStateAsyncTask. En règle générale, cela signifie que l’exception d’appel de grain est renvoyée à l’appelant client, à condition que celle-ci WriteStateAsyncTask soit correctement chaînée dans le retour Task final de cette méthode de grain. Toutefois, dans certains scénarios avancés, vous pouvez écrire du code grain pour gérer spécifiquement ces erreurs d’écriture, de la même manière que pour toute autre erreur Task.
Les grains exécutant le code de gestion des erreurs ou de récupération doivent intercepter les exceptions ou les erreurs WriteStateAsyncTasket ne pas les réactiver, ce qui signifie qu’ils ont correctement géré l’erreur d’écriture.
Recommandations
Utiliser la sérialisation JSON ou un autre format de sérialisation à tolérance de version
Le code évolue, ce qui inclut souvent des types de stockage. Pour prendre en charge ces modifications, configurez un sérialiseur approprié.
Orleans À compter de la version 7.0, vous pouvez configurer le sérialiseur de stockage des grains à l’aide de l’interfaceIGrainStorageSerializer. Par défaut, l’état du grain est sérialisé via JSON (Newtonsoft.Json). Assurez-vous que lors de l’évolution des contrats de données, les données déjà stockées peuvent toujours être chargées. Pour plus d’informations, consultez les sérialiseurs de stockage de grain.
Le code évolue, ce qui inclut souvent des types de stockage. Pour prendre en charge ces modifications, configurez un sérialiseur approprié. Pour la plupart des fournisseurs de stockage, une UseJson option ou similaire est disponible pour utiliser JSON comme format de sérialisation. Assurez-vous que lors de l’évolution des contrats de données, les données déjà stockées peuvent toujours être chargées.
Utiliser Grain<TGrainState> pour ajouter du stockage à un grain
Important
L’utilisation Grain<TGrainState> pour ajouter du stockage à un grain est considérée comme une fonctionnalité héritée . Ajoutez un stockage de grains en utilisant IPersistentState<TState> comme décrit précédemment.
Les classes de grain qui héritent de Grain<TGrainState> (où T est un type de données d’état spécifique à l’application nécessitant une persistance) ont leur état chargé automatiquement à partir du stockage spécifié.
Marquez ces grains avec une StorageProviderAttribute instance nommée d’un fournisseur de stockage à utiliser pour lire/écrire les données d’état pour ce grain.
[StorageProvider(ProviderName = "store1")]
public class MyGrain : Grain<MyGrainState>, IMyGrain
{
public Task DoSomethingAsync() => Task.CompletedTask;
}
La Grain<TGrainState> classe de base définit les méthodes suivantes pour les sous-classes à appeler :
public abstract class GrainBaseExample<TState>
{
protected virtual Task ReadStateAsync() { return Task.CompletedTask; }
protected virtual Task WriteStateAsync() { return Task.CompletedTask; }
protected virtual Task ClearStateAsync() { return Task.CompletedTask; }
}
Le comportement de ces méthodes correspond à leurs équivalents sur IPersistentState<TState> définis plus tôt.
Créer un fournisseur de stockage
Il existe deux parties aux API de persistance d’état : l’API exposée au grain via IPersistentState<TState> ou Grain<TGrainState>, et l’API du fournisseur de stockage, centrée autour IGrainStorage: les fournisseurs de stockage d’interface doivent implémenter :
/// <summary>
/// Interface to be implemented for a storage able to read and write Orleans grain state data.
/// </summary>
public interface ICustomGrainStorage
{
/// <summary>Read data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">State data object to be populated for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Read operation on the specified grain.</returns>
Task ReadStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
/// <summary>Write data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">State data object to be written for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Write operation on the specified grain.</returns>
Task WriteStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
/// <summary>Delete / Clear data function for this storage instance.</summary>
/// <param name="stateName">Name of the state for this grain</param>
/// <param name="grainId">Grain ID</param>
/// <param name="grainState">Copy of last-known state data object for this grain.</param>
/// <typeparam name="T">The grain state type.</typeparam>
/// <returns>Completion promise for the Delete operation on the specified grain.</returns>
Task ClearStateAsync<T>(
string stateName, GrainId grainId, IGrainState<T> grainState);
}
/// <summary>
/// Interface to be implemented for a storage able to read and write Orleans grain state data.
/// </summary>
public interface IGrainStorage
{
/// <summary>Read data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">State data object to be populated for this grain.</param>
/// <returns>Completion promise for the Read operation on the specified grain.</returns>
Task ReadStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
/// <summary>Write data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">State data object to be written for this grain.</param>
/// <returns>Completion promise for the Write operation on the specified grain.</returns>
Task WriteStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
/// <summary>Delete / Clear data function for this storage instance.</summary>
/// <param name="grainType">Type of this grain [fully qualified class name]</param>
/// <param name="grainReference">Grain reference object for this grain.</param>
/// <param name="grainState">Copy of last-known state data object for this grain.</param>
/// <returns>Completion promise for the Delete operation on the specified grain.</returns>
Task ClearStateAsync(
string grainType, GrainReference grainReference, IGrainState grainState);
}
Créez un fournisseur de stockage personnalisé en implémentant cette interface et en inscrivant cette implémentation. Pour obtenir un exemple d’implémentation de fournisseur de stockage existante, consultez AzureBlobGrainStorage.
Sémantique du fournisseur de stockage
Une valeur opaque spécifique au fournisseur Etag (string) peut être définie par un fournisseur de stockage dans le cadre des métadonnées d'état de grain établies lors de la lecture de l'état. Certains fournisseurs peuvent choisir de laisser cela comme null s’ils n’utilisent Etagpas.
Toute tentative d’exécution d’une opération d’écriture lorsque le fournisseur de stockage détecte une violation de Etag contrainte doit provoquer l’erreur d’écriture Task avec une erreur InconsistentStateException temporaire et encapsuler l’exception de stockage sous-jacente.
public class InconsistentStateException : OrleansException
{
public InconsistentStateException(
string message,
string storedEtag,
string currentEtag,
Exception storageException)
: base(message, storageException)
{
StoredEtag = storedEtag;
CurrentEtag = currentEtag;
}
public InconsistentStateException(
string storedEtag,
string currentEtag,
Exception storageException)
: this(storageException.Message, storedEtag, currentEtag, storageException)
{
}
/// <summary>The Etag value currently held in persistent storage.</summary>
public string StoredEtag { get; }
/// <summary>The Etag value currently held in memory, and attempting to be updated.</summary>
public string CurrentEtag { get; }
}
Toute autre condition d’échec d’une opération de stockage doit provoquer la rupture du retour Task avec une exception indiquant le problème de stockage sous-jacent. Dans de nombreux cas, cette exception peut être renvoyée à l’appelant qui a déclenché l’opération de stockage en appelant une méthode sur le grain. Il est important de déterminer si l’appelant peut désérialiser cette exception. Par exemple, le client n’a peut-être pas chargé la bibliothèque de persistance spécifique contenant le type d’exception. Pour cette raison, il est conseillé de transformer des exceptions de manière à ce qu'elles puissent se propager jusqu'à l'appelant.
Mappage des données
Les fournisseurs de stockage individuels doivent décider de la meilleure façon de stocker l'état des grains : blob (différents formats / formes sérialisées) ou un champ par colonne qui sont des choix évidents.
Inscrire un fournisseur de stockage
Lorsque un grain est créé, le runtime Orleans localise un fournisseur de stockage à partir du fournisseur de services (IServiceProvider). Le runtime résout une instance de IGrainStorage. Si le fournisseur de stockage est nommé (par exemple, via l’attribut [PersistentState(stateName, storageName)]), alors une instance nommée de IGrainStorage est résolue.
Pour inscrire une instance nommée de IGrainStorage, utilisez la méthode d’extension, en suivant l’exemple AddSingletonNamedService du fournisseur AzureTableGrainStorage ici.
Persistance des grains Redis
Redis est un magasin de données en mémoire populaire qui peut être utilisé pour la persistance des grains. Microsoft.Orleans. Le package Persistence.Redis fournit un fournisseur de stockage de grain soutenu par Redis.
Configurer le stockage des grains Redis
Configurez le stockage des grains Redis à l’aide de la méthode d’extension AddRedisGrainStorage :
var builder = Host.CreateApplicationBuilder();
builder.UseOrleans(siloBuilder =>
{
siloBuilder.AddRedisGrainStorage(
name: "redis",
configureOptions: options =>
{
options.ConfigurationOptions = new ConfigurationOptions
{
EndPoints = { "localhost:6379" },
AbortOnConnectFail = false
};
});
});
using var host = builder.Build();
Pour configurer Redis comme fournisseur de stockage de grain par défaut, utilisez AddRedisGrainStorageAsDefault:
siloBuilder.AddRedisGrainStorageAsDefault(options =>
{
options.ConfigurationOptions = new ConfigurationOptions
{
EndPoints = { "localhost:6379" }
};
});
Options de stockage Redis
La RedisStorageOptions classe fournit les options de configuration suivantes :
| Propriété | Type | Descriptif |
|---|---|---|
ConfigurationOptions |
ConfigurationOptions |
Configuration du client StackExchange.Redis. Obligatoire. |
DeleteStateOnClear |
bool |
Indique s’il faut supprimer l'état de Redis quand ClearStateAsync est appelé. La valeur par défaut est false. |
EntryExpiry |
TimeSpan? |
Délai d’expiration facultatif pour les entrées. Définissez-le uniquement pour les environnements éphémères tels que les tests, car il peut entraîner des activations en double. La valeur par défaut est null. |
GrainStorageSerializer |
IGrainStorageSerializer |
Sérialiseur à utiliser pour l’état du grain. La valeur par défaut utilise le Orleans sérialiseur. |
CreateMultiplexer |
Func<RedisStorageOptions, Task<IConnectionMultiplexer>> |
Fabrique personnalisée pour la création du multiplexeur de connexion Redis. |
GetStorageKey |
Func<string, GrainId, RedisKey> |
Fonction personnalisée pour générer la clé Redis pour un grain. Le format par défaut est {ServiceId}/state/{grainId}/{grainType}. |
Intégration de .NET Aspire
Lorsque vous utilisez .NET Aspire, vous pouvez intégrer le stockage des grains Redis à la ressource Redis gérée par Aspire.
// In your AppHost project
var redis = builder.AddRedis("orleans-redis");
var orleans = builder.AddOrleans("cluster")
.WithGrainStorage("Default", redis);
builder.AddProject<Projects.OrleansServer>("silo")
.WithReference(orleans)
.WaitFor(redis);
// Register the Redis client with keyed services.
// Orleans providers look up resources by their keyed service name.
// builder.AddKeyedRedisClient("orleans-redis");
builder.UseOrleans(siloBuilder =>
{
siloBuilder.AddRedisGrainStorage(
name: "redis",
configureOptions: options =>
{
// Use the Aspire-provided connection string
var connectionString = builder.Configuration.GetConnectionString("orleans-redis");
options.ConfigurationOptions = ConfigurationOptions.Parse(connectionString!);
});
});
Pour les scénarios plus avancés, vous pouvez injecter directement le IConnectionMultiplexer à l'aide du délégué CreateMultiplexer :
// Register the Redis client with keyed services.
// Orleans providers look up resources by their keyed service name.
// builder.AddKeyedRedisClient("orleans-redis");
siloBuilder.AddRedisGrainStorage("redis");
siloBuilder.Services.AddOptions<Orleans.Persistence.RedisStorageOptions>("redis")
.Configure<IServiceProvider>((options, sp) =>
{
options.CreateMultiplexer = _ =>
{
// Resolve the IConnectionMultiplexer from DI (provided by Aspire)
return Task.FromResult(sp.GetRequiredService<IConnectionMultiplexer>());
};
});
Persistance des grains Azure Cosmos DB
Azure Cosmos DB est une base de données NoSQL et relationnelle complètement managée pour développer des applications modernes. Le Microsoft.Orleans.Persistence.Cosmos package fournit un fournisseur de stockage de grain soutenu par Cosmos DB.
Configurer le stockage des grains Cosmos DB
Installez le paquet NuGet Microsoft.Orleans.Persistence.Cosmos :
dotnet add package Microsoft.Orleans.Persistence.Cosmos
Configurez le stockage de grains Cosmos DB en utilisant la méthode d'extension AddCosmosGrainStorage.
var builder = Host.CreateApplicationBuilder();
builder.UseOrleans(siloBuilder =>
{
siloBuilder.AddCosmosGrainStorage(
name: "cosmos",
configureOptions: options =>
{
options.ConfigureCosmosClient(
"https://myaccount.documents.azure.com:443/",
new DefaultAzureCredential());
options.DatabaseName = "Orleans";
options.ContainerName = "OrleansStorage";
options.IsResourceCreationEnabled = true;
});
});
Pour configurer Cosmos DB comme fournisseur de stockage grain par défaut, utilisez AddCosmosGrainStorageAsDefault:
siloBuilder.AddCosmosGrainStorageAsDefault(options =>
{
options.ConfigureCosmosClient(
"https://myaccount.documents.azure.com:443/",
new DefaultAzureCredential());
options.IsResourceCreationEnabled = true;
});
Options de stockage Cosmos DB
La CosmosGrainStorageOptions classe fournit les options de configuration suivantes :
| Propriété | Type | Par défaut | Descriptif |
|---|---|---|---|
DatabaseName |
string |
"Orleans" |
Nom de la base de données Cosmos DB. |
ContainerName |
string |
"OrleansStorage" |
Nom du conteneur pour les données d’état du grain. |
IsResourceCreationEnabled |
bool |
false |
Quand true, crée automatiquement la base de données et le conteneur s’ils n’existent pas. |
DeleteStateOnClear |
bool |
false |
Indique s’il faut supprimer l’état de Cosmos DB lorsque ClearStateAsync est appelé. |
InitStage |
int |
ServiceLifecycleStage.ApplicationServices |
Étape du cycle de vie du silo lors de l’initialisation du stockage. |
StateFieldsToIndex |
List<string> |
Vide | Chemins JSON des propriétés d'état à inclure dans l'index de Cosmos DB. |
PartitionKeyPath |
string |
"/PartitionKey" |
Chemin JSON de la clé de partition dans le conteneur. |
DatabaseThroughput |
int? |
null |
Débit provisionné pour la base de données. Si null, utilise le mode serverless. |
ContainerThroughputProperties |
ThroughputProperties? |
null |
Propriétés de débit du conteneur. |
ClientOptions |
CosmosClientOptions |
new() |
Options transmises au client Cosmos DB. |
Fournisseur de clés de partition personnalisée
Par défaut, Orleans utilise l’ID de grain comme clé de partition. Pour les scénarios avancés, vous pouvez implémenter un fournisseur de clés de partition personnalisé :
public class MyPartitionKeyProvider : IPartitionKeyProvider
{
public ValueTask<string> GetPartitionKey(string grainType, GrainId grainId)
{
// Custom logic to determine partition key
return new ValueTask<string>(grainId.Key.ToString()!);
}
}
Inscrivez le fournisseur de clés de partition personnalisée :
// Register with custom partition key provider
siloBuilder.AddCosmosGrainStorage<MyPartitionKeyProvider>(
name: "cosmos",
configureOptions: options =>
{
options.ConfigureCosmosClient("https://myaccount.documents.azure.com:443/", new DefaultAzureCredential());
});