Partager via


Gestion de la perte de connectivité

Une fois l’appel RPC terminé, la connexion n’est pas fermée ; il est marqué comme gratuit. Par conséquent, le serveur peut tomber en panne ou la connectivité réseau peut être perdue pendant ou entre les appels, alors qu’une connexion se trouve dans le pool. Par stratégie, le temps d’exécution RPC tente de nouveau ces appels uniquement si les deux conditions suivantes sont remplies :

  • Le serveur ne peut pas exécuter l’appel ou l’appel est idempotent.
  • Le client peut implémenter les nouvelles tentatives de manière efficace.

Les paragraphes suivants développent et clarifient les deux conditions.

Un appel idempotent est un appel qui peut être exécuté plusieurs fois sur le serveur sans effets secondaires indésirables. Par exemple, avoir un appel RPC qui interroge le solde dans la banque pour un compte donné est idempotent. Si cet appel est exécuté deux fois en raison d’une perte de connectivité, aucun dommage n’est effectué. Un autre exemple d’appel idempotent est la modification de l’adresse d’un client dans une base de données. L’exécution à deux reprises est correcte, car la deuxième exécution remplace simplement l’adresse déjà actuelle par la même adresse. Une opération comme « soustraire cinquante dollars du compte xyz » n’est pas idempotente. La perte de connectivité réseau ne doit pas entraîner plusieurs exécutions d’un tel appel.

Par mesure de sécurité, le temps d’exécution RPC traite tous les appels comme non idempotents. L’attribut [idempotent] n’est pas pris en charge pour ncacn_ip_tcp et est ignoré. Par conséquent, la première condition de la liste précédente est réduite au serveur qui ne peut pas exécuter l’appel.

Dans de nombreux cas, le temps d’exécution rpc n’est pas en mesure de déterminer de manière concluante que l’appel n’a pas déjà été exécuté sur le serveur. Dans ce cas, le client ne réessayera pas d’exécuter l’appel.

Les exemples suivants illustrent quand l’exécution du RPC effectue ou non une nouvelle tentative d’appel :

  • Un serveur est redémarré.

    Un simple appel RPC sans sécurité est effectué sur une interface sur laquelle aucun appel précédent n’a été effectué après le redémarrage. Étant donné qu’aucun appel n’a été effectué sur cette interface, l’exécution RPC tente d’abord de négocier l’utilisation de l’interface. Il envoie un paquet à l’aide d’une connexion dans le pool. Étant donné que le serveur a été redémarré et que la connexion n’est plus valide, il retourne une erreur. Étant donné que l’exécution RPC côté client n’a pas encore commencé à envoyer les données pour l’appel réel, le client détermine que le serveur n’aurait pas pu s’exécuter sur ces données. Par conséquent, il ferme la connexion et recherche une autre connexion dans le pool. S’il ne trouve pas de connexion, il ouvre une nouvelle connexion et tente à nouveau de négocier l’utilisation de l’interface. Si cela réussit, l’appel est effectué (autrement dit, une nouvelle tentative est effectuée, car l’échec a été détecté avant le démarrage de l’appel).

  • Un appel RPC avec une sécurité au niveau de la confidentialité (chiffrement) est effectué sur une connexion avec un contexte de sécurité déjà négocié.

    Pour garantir des performances efficaces, le temps d’exécution RPC chiffre le paquet marshalé en ligne (sur les données de texte clair). Si la tentative d’envoi des données échoue, l’heure d’exécution RPC ne peut pas réessayer l’appel, car les données en texte clair ont été remplacées par les données chiffrées et ne peuvent pas rechiffrer les données avec un nouveau contexte de sécurité. Par conséquent, aucune nouvelle tentative n’est effectuée.

  • L’envoi d’un fragment autre que le premier échoue.

    La nouvelle tentative n’est pas effectuée, car l’heure d’exécution RPC peut choisir d’ignorer le contenu du premier fragment une fois qu’elle est terminée et n’a aucun moyen de réessayer d’envoyer le premier fragment.

  • La demande RPC est envoyée.

    Le serveur interrompt la connexion. Aucune nouvelle tentative n’est effectuée, car RPC ne peut pas déterminer si le serveur a reçu l’appel et a commencé à l’exécuter.

Si le serveur utilise un point de terminaison dynamique, RPC ne résoudra pas le point de terminaison pendant les nouvelles tentatives. Cela signifie que si un serveur est mis hors service et qu’il revient, il peut résider sur un autre point de terminaison, et RPC ne résolve pas de manière transparente le point de terminaison lorsqu’un appel est retenté. Pour forcer la résolution du point de terminaison, le client RPC doit appeler RpcBindingReset avant d’effectuer une nouvelle tentative d’appel.

Dans la plupart de ces cas, si un client RPC peut déterminer si un appel est idempotent ou s’il conserve les données que RPC ignore, il peut choisir de créer un mécanisme de nouvelle tentative par-dessus RPC.

Notes

Si le serveur est un cluster et que les différents nœuds du cluster exécutent des versions différentes du logiciel serveur, une nouvelle tentative RPC peut faire atterrir l’appel sur un autre nœud du cluster en cas de basculement, et potentiellement sur une autre version du serveur. Dans de tels scénarios de déploiement, assurez-vous que le client ne s’appuie pas sur une version particulière du logiciel serveur pour exécuter un appel donné. Si c’est le cas, le client doit créer un mécanisme au-dessus de RPC qui détecte et gère ces conditions.