Passer au contenu principal

La capture TCP Backlog est un effet qui empêche une application serveur sur le Stratus écoutant sur le port X de créer une connexion avec un client essayant de se connecter au port X. Les connexions à d'autres ports, même à partir des mêmes clients, fonctionnent correctement. La solution habituelle consiste à arrêter et redémarrer l'application serveur. Cet article explique pourquoi la capture Backlog se produit et propose d'autres solutions moins radicales.

Le backlog TCP est la file d'attente des connexions en attente, c'est-à-dire les demandes de connexion qui ont été reçues mais qui n'ont pas encore été acceptées. Dans les applications compilées sur des versions antérieures à OpenVOS 17.1 et dans les applications compilées sur OpenVOS 17.1 mais sans les bibliothèques POSIX, les demandes de connexion ne reçoivent pas d'accusé de réception tant qu'elles n'ont pas été acceptées par l'application. Le client renvoie le paquet de demande de connexion entre 3 et 10 fois à des intervalles croissants. Les détails exacts dépendent du système d'exploitation du client et de sa configuration. À un moment donné, l'application serveur accepte la demande de connexion et la pile STCP envoie un accusé de réception. Tant que cet accusé de réception est reçu avant que le client n'abandonne, la connexion sera établie et la communication pourra commencer.

Le scénario de capture des commandes en attente nécessite plusieurs conditions

  1. Il y a une défaillance temporaire du réseau entre le serveur et le client (mais pas entre le client et le serveur). Cela permet au serveur de recevoir les demandes de connexion du client, mais empêche le client de recevoir les accusés de réception de connexion du serveur.
    ou

    L'application serveur retarde l'appel de la fonction accept pour une raison quelconque.

  2. Le client continue d'envoyer des demandes de connexion ; c'est-à-dire que lorsque la demande en cours expire, le client en envoie une nouvelle. La valeur du délai d'expiration du client doit être inférieure à celle du serveur.
  3. Un pare-feu avec état ou un autre dispositif situé quelque part entre le client et le serveur expire les demandes de connexion du client et rejette les accusés de réception de connexion du serveur sans renvoyer de réponse au serveur. Cette valeur d'expiration doit être inférieure à la valeur d'expiration du serveur.

Malheureusement, cette combinaison de conditions n'est pas aussi improbable qu'elle pourrait le paraître à première vue.

Cela commence généralement par une panne de réseau qui empêche les paquets provenant du serveur d'atteindre le client, mais permet aux paquets provenant du client d'atteindre le serveur. Lorsque le paquet de demande de connexion du client atteint le serveur, il est placé dans la file d'attente. Lorsque l'application serveur appelle le code d'acceptation, celui-ci extrait la demande de connexion de la file d'attente et envoie un accusé de réception de connexion. Comme le serveur ne reçoit pas d'accusé de réception pour son paquet, en raison de la panne du réseau, il retransmet l'accusé de réception de connexion. La pile TCP du client retransmet également la demande de connexion, car elle n'a pas reçu d'accusé de réception. Au bout d'un certain temps, la pile TCP du client abandonne et l'application cliente envoie une nouvelle requête. Le serveur continue de répondre à la première requête. Après environ une minute et demie (par défaut), le serveur expire et extrait la requête suivante de la file d'attente. Entre-temps, le client a renvoyé la deuxième demande et en est peut-être à la troisième. Ces demandes se trouvent également dans la file d'attente. Il est possible qu'un autre client obtienne une demande de connexion placée dans la file d'attente, mais pour qu'elle aboutisse, le client aurait besoin d'un délai d'expiration supérieur au délai d'expiration du serveur multiplié par la position de la demande de connexion dans la file d'attente. Une fois la panne réseau corrigée, le pare-feu avec état perpétue la panne en supprimant silencieusement les accusés de réception de connexion pour lesquels il n'a plus d'état, car il ne conserve l'état que pendant une durée inférieure au délai d'expiration du serveur.

Comment reconnaissez-vous cela ?

Tout d'abord, la file d'attente est pleine ou presque pleine. Vous pouvez afficher la file d'attente pour une connexion à l'aide de cette commande.

analyze_system -request_line (chaîne de caractères correspondante backlog -ou syncnt (octet 3Bx) dump_st + 
cbq -full -lport 7654 -faddr 0x) -quit 
OpenVOS version 17.0.2au, analyze_system version 17.0.2au 
Le processus actuel est 154, ptep 91CC7100, Noah_Davids.CAC 
syncnt                        6 
backlog                       5 
ready  11:41:19

La valeur lport correspond au numéro de port local, 7654 dans le cas présent. La valeur d'adresse étrangère (faddr) de 0 limite la sortie au seul socket LISTENING. Si la valeur backlog plus 1 est égale à la valeur syncnt, le backlog est plein. Si syncnt est supérieur à 0 et augmente, la file d'attente du backlog se remplit. La taille de la file d'attente du backlog est définie par l'application lorsqu'elle appelle la fonction listen.

Ensuite, vous devez examiner une trace du protocole réseau. La trace montrera que la dernière demande de connexion n'est pas confirmée, alors qu'il existe des confirmations de connexion pour une demande de connexion précédente et que ces confirmations ne reçoivent aucune réponse.

La trace de la figure 1 illustre ce processus. Chaque connexion est identifiée par un index de flux et un code couleur. La première demande de connexion du client se trouve dans la trame 1 à l'instant 0. L'accusé de réception est envoyé dans la trame 2, puis retransmis dans la trame 3. La trame 4 correspond à la retransmission de la demande de connexion par le client. Étant donné que STCP envoie déjà des accusés de réception de connexion, la trame 4 ne déclenche qu'un accusé de réception TCP dans la trame 5. Les trames 6 et 7 sont des accusés de réception de connexion retransmis. La trame 8 est une demande de connexion retransmise par le client. La trame 9 est l'accusé de réception TCP déclenché par la demande de connexion retransmise et la trame 10 est un autre accusé de réception de connexion retransmis. La trame 11 est une autre demande de connexion du client, mais pour une nouvelle deuxième connexion. Notez qu'il n'y a pas de réponse et que la trame 12 montre une demande de connexion retransmise. La trame 13 montre un accusé de réception de connexion, mais il s'agit toujours de la première connexion. La trame 14 est une retransmission de la deuxième demande de connexion. La trame 14 est une autre retransmission de la deuxième demande de connexion. La trame 15 montre une nouvelle troisième demande de connexion provenant du client et les trames 16 et 17 sont des retransmissions. La trame 18 est une autre retransmission de l'accusé de réception de connexion pour la première connexion. La trame 19 est une autre demande de connexion, les trames 20 et 21 sont des retransmissions et la trame 22 est la quatrième nouvelle demande de connexion. Enfin, dans la trame 23, STCP abandonne la première demande de connexion et envoie une réinitialisation suivie, dans la trame 24, d'un accusé de réception de la deuxième demande de connexion avec une retransmission dans la trame 25. À ce stade, je pense que vous avez compris le principe.

Le STCP a mis entre 106,9 secondes pour passer de la trame 0 à la trame 23. Bien que le client n'envoie pas de réinitialisation lorsqu'il expire, le temps entre le début de la deuxième et de la troisième requête de connexion (trames 11 à 15) est de 29,152 secondes et entre la troisième et la quatrième (trames 15 et 19) est de 25,8 secondes, ce qui est beaucoup plus rapide que STCP.

Que pouvez-vous faire pour éviter cela ?

La meilleure solution consiste à passer à OpenVOS 17.1 et à recompiler l'application avec les bibliothèques POSIX. Cela permettra d'éviter que le problème ne se reproduise, car STCP enverra immédiatement un accusé de réception de connexion, sans attendre que l'application appelle accept. Cela peut toutefois modifier d'autres comportements de votre application et il convient de la tester minutieusement. Si la mise à niveau et la recompilation ne sont pas possibles, vous pouvez

  1. Reconfigurez le périphérique réseau avec état qui rejette les accusés de réception de connexion afin qu'il réponde par une réinitialisation. Lorsque STCP reçoit la réinitialisation, il passe à la demande de connexion suivante dans la file d'attente. Ainsi, les demandes de connexion expirées par le périphérique avec état sont rapidement supprimées de la file d'attente. Tout autre accusé de réception de connexion sera traité par le client, qui enverra sa propre réinitialisation ou les accusera réception.
  2. Empêcher le client d'envoyer des demandes de connexion jusqu'à ce que la file d'attente du serveur soit vide.
  3. Fermez le socket d'écoute de l'application serveur et rouvrez-le. En général, l'application n'est pas conçue pour cela, vous devez donc arrêter et redémarrer l'application serveur.
  4. Configurez la valeur syn_rcvd_abort sur une valeur inférieure à la valeur de délai d'expiration du client. La valeur est modifiée à l'aide de la requête analyze_system set_stcp_param.
    analyze_system -request_line 'set_stcp_param syn_rcvd_abort 15' -quit 
    OpenVOS version 17.0.2au, analyze_system version 17.0.2au 
    Le processus actuel est 151, ptep 91530AC0, Noah_Davids.CAC 
    Modification du délai d'expiration SYN_RCVD (syn_rcvd_abort) de tcp de off à 15 
    prêt  11:07:44

    Dans l'exemple ci-dessus, le délai d'expiration est défini sur 15 secondes. Les valeurs valides sont comprises entre 1 et 180, la valeur 0 signifiant l'utilisation de la valeur par défaut (environ 100 secondes).

    Cela empêchera un seul client de créer une accumulation importante dans la file d'attente. La valeur minimale dépendra du nombre de clients pouvant accéder au serveur simultanément. Le problème avec cette approche est qu'elle affecte tous les clients et tous les ports du serveur. Vous ne pouvez pas avoir une valeur pour un ensemble de ports et une autre pour un autre ensemble de ports. De plus, une valeur trop faible peut entraîner l'échec de certaines connexions passant par des liaisons à forte latence, alors qu'elles auraient pu aboutir si le délai avait été plus long. Choisir une valeur optimale relève davantage de l'art que de la science.