|
|
|
|
||||||
| fr.comp.reseaux.ip IP : Discussions techniques, protocoles connexes. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonsoir,
Je rencontre actuellement des problemes de fermetures de connexions tcp sur un Linux. Pour le mettre en evidence, j'ai ecrit un petit serveur d'echo qui accepte plusieurs milliers de connexions par processus, et un client capable de maintenir plusieurs milliers de connexions simultanees. Les serveurs ne font que repondre aux sollicitations des clients. Ceux-ci ouvrent des connexions vers les serveurs, font un peu de trafic, attendent, ferment les connexions, et les rouvrent, etc... Toutes les sockets sont non-bloquantes (pooling via un appel a select). Tous les processus sont mono-threades. Pour etre capable d'atteindre un nombre appreciable de connexions sur les processus client, j'ai du positionner l'option SO_LINGER pour eviter d'accumuler les connexions dans l'etat TIME_WAIT. Sur les clients, j'ai pu remarquer que si le time_out passe a l'option SO_LINGER est trop court, et qu'il y a plus de 4000 connexions etblies, alors un arret brutal des processus clients (SIGTERM ou SIGQUIT) provoque la fermeture (paquet TCP RST) d'une partie seulement des connexions. C'est particulierement problematique car le serveur n'ayant aucune nouvelle, il considere que ces connexions sont toujours dans leur etat ESTABLISHED. Une trace des communications montre explicitement que les paquets RST ne sont pas emis du tout de la machine qui portait les clients. Il n'y a aucune trace d'un quelconque message kernel qui indique une erreur. Plus le time-out de SO_LINGER est grand, plus l'OS arrive a fermer une grande partie des connexions etablies avec des paquets TCP FIN (celles qu'il peut clore dans les temps), plus il peut en remettre a zero (celles hors delai, via un paquet TCP RST), et plus le nombre de connexions mortes sur le serveur est petit. L'utilisation du mecanisme de tcp_keepalive permet de se rendre compte des coupures mal detectees, mais les valeurs par defaut (2h avant de s'y mettre) sont trop longues pour etre utilisables. Avez-vous deja pu remarquer des comportements semblables? Sont-ils connus? Ont-ils des correctifs? Merci beaucoup, Jean-Francois SMIGIELSKI PS: mon mailer a quelques soucis avec les accents, ce qui explique leur absence dans mon message. Que vive l'UTF-8! |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Jean-Francois Smigielski wrote:
> Pour etre capable d'atteindre un nombre appreciable de connexions sur les > processus client, j'ai du positionner l'option SO_LINGER pour eviter > d'accumuler les connexions dans l'etat TIME_WAIT. Question stupide: si vous n'utilisez pas cette option, que se passe-t-il ? (avec SO_REUSEADDR sur bind() evidemment) > Sur les clients, j'ai pu remarquer que si le time_out passe a l'option > SO_LINGER est trop court, et qu'il y a plus de 4000 connexions etblies, > alors un arret brutal des processus clients (SIGTERM ou SIGQUIT) provoque > la fermeture (paquet TCP RST) d'une partie seulement des connexions. Hmm, sur un kernel récent ? C'est un comportement assez étonnant.. > C'est particulierement problematique car le serveur n'ayant aucune > nouvelle, il considere que ces connexions sont toujours dans leur etat > ESTABLISHED. Encore une suggestion stupide: un sigaction() qui trappe les SIGTERM/etc., et qui referme proprement les sockets, en dernier recours ? > L'utilisation du mecanisme de tcp_keepalive permet de se rendre compte > des coupures mal detectees, mais les valeurs par defaut (2h avant de s'y > mettre) sont trop longues pour etre utilisables. Et TCP keepalive semble déconseillé un peu partout. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On 2007-03-07, Xavier Roche <XXXXXXXXXXXXXXXXXXXXXXXXXXXXX> wrote:
> Jean-Francois Smigielski wrote: >> Pour etre capable d'atteindre un nombre appreciable de connexions sur les >> processus client, j'ai du positionner l'option SO_LINGER pour eviter >> d'accumuler les connexions dans l'etat TIME_WAIT. > > Question stupide: si vous n'utilisez pas cette option, que se passe-t-il > ? (avec SO_REUSEADDR sur bind() evidemment) La question n'est pas stupide du tout. Si l'option SO_LINGER n'est pas positionnee, les sockets qui se referment restent pres de 2 minutes dans l'etat TIME_WAIT. Comme les clients tentent d'ouvri rbeaucoup de connexions simultanees, il arrive un moment ou cela n'est plus possible, faute de file_descriptors. > >> Sur les clients, j'ai pu remarquer que si le time_out passe a l'option >> SO_LINGER est trop court, et qu'il y a plus de 4000 connexions etblies, >> alors un arret brutal des processus clients (SIGTERM ou SIGQUIT) provoque >> la fermeture (paquet TCP RST) d'une partie seulement des connexions. > > Hmm, sur un kernel récent ? C'est un comportement assez étonnant.. Le kernel est "relativement" recent, il s'agit d'un Linux 2.6.18 compile sans option particuliere. > >> C'est particulierement problematique car le serveur n'ayant aucune >> nouvelle, il considere que ces connexions sont toujours dans leur etat >> ESTABLISHED. > > Encore une suggestion stupide: un sigaction() qui trappe les > SIGTERM/etc., et qui referme proprement les sockets, en dernier recours ? Tout a fait, et c'est comme cela que j'ai du proceder. Mais le probleme persiste encore : un appel a close sur les sockets qui utilisent l'option SO_LINGER donne le meme resultat que l'arret du processus. > >> L'utilisation du mecanisme de tcp_keepalive permet de se rendre compte >> des coupures mal detectees, mais les valeurs par defaut (2h avant de s'y >> mettre) sont trop longues pour etre utilisables. > > Et TCP keepalive semble déconseillé un peu partout. Oui. le tcp keepalive n'est pas une operation anodine en terme de charge CPU. Pour detecter rapidement les connexions mortes, j'ai rabaisse le delai de 2 heures a 1 minute. Sur une machine equipee de 2 processeurs Intel Xeon cadences a 3GHz, ca a pris 15% du CPU pendant plusieurs secondes pour refermer toutes les connexions mortes (a peu pres 17000). JF Smigielski. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
Jean-Francois Smigielski wrote:
> l'etat TIME_WAIT. Comme les clients tentent d'ouvri rbeaucoup de > connexions simultanees, il arrive un moment ou cela n'est plus possible, > faute de file_descriptors. Hmm, cela ne devrait pas ? Il y a juste une paire locale/remote côté kernel pour finir le nettoyage, mais cela consomme vraiment un fd ? > Tout a fait, et c'est comme cela que j'ai du proceder. Mais le probleme > persiste encore : un appel a close sur les sockets qui utilisent l'option > SO_LINGER donne le meme resultat que l'arret du processus. Damned. Vous êtes en socket non bloquante ? close() ne renvoi pas EINTR par hasard ? [le close() peut être bloquant..] |
|
![]() |
| Outils de la discussion | |
|
|