Prévention des blocages côté client
Votre client peut se bloquer de deux façons : la connectivité réseau peut entraîner la perte des demandes du serveur ou le serveur lui-même peut se bloquer. Avec les options par défaut, RPC n’expire jamais un appel, et votre thread client attend toujours une réponse.
Il existe deux méthodes pour éviter cela : maintenir en vie et délais d’expiration.
TCP Keep Alives
Le client peut être configuré pour effectuer régulièrement un test ping sur le serveur pour s’assurer que le serveur est actif et en cours d’exécution. Les pings sont des keep-alives TCP pour les séquences de protocole ncacn_ip_tcp et ncacn_http , et par conséquent, ils sont efficaces en matière d’utilisation du processeur et de bande passante réseau. Pour activer la fonctionnalité keep alives sur un appel de procédure distante donné, utilisez la fonction RpcMgmtSetComTimeout avant le lancement de l’appel. Cette fonction prend un handle de liaison et un délai d’attente en tant qu’arguments. Chaque appel de procédure distante sur ce handle de liaison après que RpcMgmtSetComTimeout utilise le délai d’expiration fourni.
Le paramètre Timeout de la fonction RpcMgmtSetComTimeout spécifie la durée d’attente de l’exécution rpc avant qu’elle ne s’active. Le délai d’expiration est une valeur comprise entre 0 et 10, où 0 est le délai d’attente minimal et 10 est un délai d’attente infini (aucun délai d’attente). Le délai d’expiration lui-même n’est pas en secondes ; La conversion en secondes de la valeur de délai d’attente fournie à la fonction RpcMgmtSetComTimeout est effectuée par l’exécution rpc et est spécifique à l’implémentation.
Le tableau suivant fournit la traduction en secondes pour Windows 2000 et Windows XP. Les versions ultérieures de Windows peuvent modifier le mappage entre le paramètre Timeout et la valeur du délai d’attente en secondes :
Paramètre timeout | Délai d’expiration réel en secondes |
---|---|
0 (RPC_C_BINDING_MIN_TIMEOUT) | 120 |
1 | 240 |
2 | 360 |
3 | 480 |
4 | 600 |
5 (RPC_C_BINDING_DEFAULT_TIMEOUT) | 720 |
6 | 840 |
7 | 960 |
8 | 1080 |
9 (RPC_C_BINDING_MAX_TIMEOUT) | 1200 |
10 (RPC_C_BINDING_INFINITE_TIMEOUT) | Délai d’expiration infini |
Une fois que les éléments keep alives sont activés, le client envoie un paquet keep alive toutes les secondes. S’il n’y a pas d’accusé de réception du serveur pour au moins trois conservations actives, le client déclare la connexion morte et échoue à l’appel de procédure distante. Si le serveur envoie une réponse dans le délai d’expiration spécifié, l’option Keep Alives n’est pas activée. Si le serveur répond à maintenir actif, mais ne répond pas à l’appel de procédure distante, le client continue d’envoyer des données keep alive. Une fois que le serveur répond à l’appel RPC, les éléments keep alive sont désactivés. Pour Windows 2000, keep alives est activé uniquement pour les appels RPC synchrones. Pour Windows XP, keep alives est également activé pour les appels RPC asynchrones.
Il est tentant de définir keep alives sur la valeur la plus faible pour s’assurer que l’application cliente répond aux problèmes réseau en temps opportun. Une attention particulière doit être accordée à cette tentation, et un examen minutieux doit être appliqué pour déterminer si une valeur agressive est justifiée. Un serveur qui perd temporairement la connectivité peut se retrouver inondé de maintiens en vie de nombreux clients une fois la connectivité restaurée. En outre, les tâches de calcul longues peuvent prendre plus de deux minutes, et le serveur peut se retrouver à consacrer plus de temps à répondre au processeur que d’effectuer un travail utile. Par conséquent, keep alives doit être utilisé avec modération. Si le client ne peut pas tolérer que son thread soit lié pendant de longues périodes, le RPC asynchrone doit être pris en compte.
D’autres séquences de protocole peuvent implémenter différents mécanismes pour détecter les serveurs qui ne répondent pas, selon le transport utilisé. Le transport ncalrpc n’utilise pas keep alives. Étant donné que toutes les communications dans ncalrpc sont locales, si le serveur ne répond plus pendant qu’un appel est en cours, l’heure d’exécution RPC sur le client échoue immédiatement à l’appel.
Délai d’expiration des appels
Les connexions TCP sont correctes si la connectivité réseau est perdue ou si le serveur plante. Toutefois, si le serveur se trouve dans un interblocage en mode utilisateur, tcp keep alives retourne correctement, mais l’appel ne revient jamais. Pour faire face à ce scénario, une nouvelle option d’exécution a été ajoutée pour Windows XP : RPC_C_OPT_CALL_TIMEOUT. Cette option indique au moment de l’exécution rpc de configurer un minuteur chaque fois qu’il envoie une demande au serveur. Si le minuteur expire, l’appel est automatiquement annulé et se termine avec RPC_S_CALL_CANCELLED. Tant que le serveur répond dans le délai spécifié, le client n’annule pas l’appel. Cela signifie qu’un appel multifragment peut prendre plus que le délai d’attente, car chaque réponse du serveur est reçue dans le délai d’expiration, même si la période d’arrivée de toutes les réponses était supérieure au délai d’attente.
En outre, lorsqu’un appel est annulé, le serveur n’est pas averti de l’annulation. Par conséquent, le serveur exécutera probablement l’appel à un moment donné, et le client ignorera simplement la réponse du serveur.
L’écueil le plus dangereux avec les délais d’expiration des appels est d’établir un court délai d’attente et de réessayer l’appel sur le même serveur. Le scénario suivant illustre les dangers de cette approche :
Imaginez un serveur qui fonctionne à proximité de la capacité. Il a un certain nombre de clients avec des délais d’attente très courts, comme cinq secondes. Une perte temporaire de connectivité réseau ou une congestion au niveau d’un routeur entraîne une défaillance des réponses du serveur pendant quelques secondes. Sur les réseaux Ethernet, cette situation peut facilement être provoquée par un pic d’activité sur une liaison que le serveur partage avec une autre machine. Le serveur ne parvient pas à envoyer toutes les réponses avant le délai d’expiration de cinq secondes. Les clients obtiennent leurs appels annulés et réessayent immédiatement. Le serveur ne sait pas que les appels sont de nouvelles tentatives et les exécute également. Ainsi, au lieu d’exécuter sa charge de travail normale d’appels, elle exécute 30 à 50 % d’appels en plus, selon le nombre de clients ayant expiré. Si cela dépasse sa capacité et que le serveur ne peut pas répondre à tous les clients dans les cinq secondes, une autre série d’appels est envoyée au serveur. Les clients continuent de réémettre les mêmes appels, et étant donné que le serveur est surchargé pour traiter les appels précédents, il ne peut pas répondre dans le délai imparti. Une fois qu’il a répondu, les clients ont atteint le délai d’expiration, ont émis un nouvel appel et ont ignoré la réponse. Dans le pire des cas, le serveur ne récupère pas avant le redémarrage et, selon le modèle d’accès au client, peut ne pas récupérer tant qu’un nombre suffisant de clients n’est pas arrêté.
Notes
Les délais d’expiration des appels fonctionnent uniquement sur les séquences de protocole ncacn_ip_tcp et ncacn_http .