Le contrôle de simultanéité optimiste (OCC) est une stratégie permettant de gérer les ressources partagées et d'éviter les pertes de mises à jour ou les conditions de concurrence lorsque plusieurs utilisateurs ou processus modifient la même ressource en même temps.
Par exemple, lorsque vous utilisez Identity and Access Management, une stratégie IAM est une ressource partagée associée à une ressource telle qu'un projet, un bucket ou un service. Sans contrôle de simultanéité, les modifications simultanées peuvent écraser les modifications récentes apportées aux stratégies, ce qui peut révoquer par inadvertance un accès légitime ou accorder des autorisations non autorisées.
Pour implémenter le contrôle de simultanéité optimiste, les systèmes utilisent généralement un numéro de version ou un champ etag (balise d'entité) sur la structure de la ressource.
Fonctionnement de l'OCC
Supposons que deux processus, A et B, tentent de mettre à jour une ressource partagée en même temps :
- Le processus A lit l'état actuel de la ressource.
- Le processus B lit le même état actuel.
- Le processus A modifie sa copie et la réécrit sur le serveur.
- Le processus B modifie sa copie et la réécrit sur le serveur.
Étant donné que le processus B écrase la ressource sans savoir que le processus A l'a déjà modifiée, les mises à jour du processus A sont perdues.
Le contrôle de simultanéité optimiste résout ce problème en introduisant une empreinte unique qui change chaque fois qu'une entité est modifiée. Dans de nombreux systèmes, tels qu'IAM, cette empreinte est un etag. Le serveur vérifie ce tag à chaque écriture :
- Lorsque vous lisez la ressource, le serveur renvoie un
etag(une empreinte unique). - Lorsque vous renvoyez la ressource modifiée, vous devez inclure l'
etagd'origine. - Si l'
etagstocké ne correspond pas à l'etagque vous avez envoyé (ce qui signifie qu'un autre processus a modifié la ressource après que vous l'avez lue), l'opération d'écriture échoue avec une erreurABORTEDouFAILED_PRECONDITION.
Cet échec indique au client qu'il doit relancer l'ensemble du processus : relire l'état mis à jour, réappliquer les modifications et réessayer l'écriture avec le nouvel etag.
Implémenter la boucle OCC
Le cœur d'une implémentation OCC est une boucle de nouvelle tentative qui lit, modifie et tente d'enregistrer la ressource, puis se ferme après une écriture réussie. Pour éviter les boucles infinies en cas de conflit élevé, configurez un nombre maximal raisonnable de tentatives.
Étapes de la boucle
Le tableau suivant décrit chaque étape d'une boucle de nouvelle tentative OCC :
| Étape | Action | Exemple de mise en œuvre |
|---|---|---|
| Read (Lire) | Récupérez l'état actuel de la ressource, y compris l'etag. |
let mut policy = client .get_iam_policy() .set_resource(&secret_name) .send() .await?; |
| Modifier | Appliquez les modifications à la structure locale. | policy.bindings.push(new_binding); |
| Rédiger et vérifier | Essayez d'enregistrer la ressource modifiée à l'aide de l'etag existant, puis recherchez les codes d'erreur de simultanéité. |
match client .set_iam_policy() .set_resource(&secret_name) .set_policy(policy) .send() .await { Ok(p) => return Ok(p), Err(e) => { /* ... */ } } |
| Réussite ou nouvel essai | Si l'écriture réussit, quittez la boucle. Si elle échoue avec une erreur de simultanéité, incrémentez le compteur de nouvelles tentatives et poursuivez la boucle à partir de l'étape Read. | - |
Exemple
L'exemple suivant montre comment implémenter une boucle OCC qui met à jour une stratégie IAM sur une ressource de secret Secret Manager en accordant le rôle roles/secretmanager.secretAccessor à un membre.
Pour exécuter cet exemple, commencez par déclarer la dépendance dans votre fichier Cargo.toml :
cargo add google-cloud-secretmanager-v1
Ensuite, implémentez la boucle de nouvelle tentative OCC :
Compléter le code
Le code suivant montre la fonction complète avec toutes les importations requises :