28 votes

nginx, fastcgi et sockets ouverts

Je suis en train d'expérimenter à l'aide de fastcgi sur nginx, mais j'ai rencontré quelques problèmes. Nginx ne pas réutiliser les connexions, il donne 0 dans BeginRequest drapeaux, de sorte que l'application doit fermer la connexion après que la demande a fini.

J'ai le code suivant pour la fermeture:

socket.shutdown(SocketShutdown.BOTH);
socket.close();

Le problème est que les connexions ne sont pas réellement fermé.. Ils s'attardent comme TIME_WAIT, et nginx (ou quelque chose) wont pas continuer à ouvrir de nouvelles connexions. Ma conjecture est que je suis en train de faire quelque chose de mal lors de la fermeture de la sockets, mais je ne sais pas quoi.. Sur une note connexe - comment puis-je obtenir nginx pour garder les connexions ouvertes?

C'est à l'aide de nginx 1.0.6 et D 2.055

EDIT: N'ai pas eu tout de plus près, mais j'ai aussi vérifié le linger option, et c'est:

linger l;
socket.getOption(SocketOptionLevel.SOCKET, SocketOption.LINGER, l);
assert(l.on == 0); // off

getOption renvoie 4 si.. Aucune idée de ce que cela signifie. La valeur de retour est sans-papiers.

EDIT: J'ai aussi essayé d'utiliser TCP_NODELAY sur le dernier message envoyé, mais cela n'avait pas du tout l'effet:

socket.setOption(SocketOptionLevel.SOCKET, SocketOption.TCP_NODELAY, 1);

EDIT: nginx 1.1.4 membres garder en vie les connexions. Cela ne fonctionne pas comme prévu mais.. Est correctement rapport que le serveur est responsable de la connexion de gestion de durée de vie, mais encore, elle crée un nouveau socket pour chaque demande.

4voto

Proxy NGINX keepalive

Concernant nginx (v1.1) keepalive pour fastcgi. La bonne façon de le configurer comme suit:

upstream fcgi_backend {
  server localhost:9000;
  keepalive 32;
}

server {
  ...
  location ~ \.php$ {
    fastcgi_keep_conn on;
    fastcgi_pass fcgi_backend;
    ...
  }
}

TIME_WAIT

TCP TIME_WAIT état de la connexion n'a rien à voir avec s'attarde, tcp_no_delays, les délais d'attente, et ainsi de suite. Il est entièrement géré par le noyau du système d'exploitation et ne peut être influencée par l'échelle du système, les options de configuration. En général, il est inévitable. C'est juste la façon protocole TCP fonctionne. Lire à ce sujet ici et ici.

La manière la plus radicale pour éviter TIME_WAIT est de réinitialiser (envoyer TVD paquet) connexion TCP près de réglage de s'attarder=SUR et linger_timeout=0. Mais cette façon de faire n'est pas recommandé pour une utilisation normale, comme vous pouvez le lâche en attente de données. Réinitialiser uniquement prise en vertu des conditions d'erreur (délais d'attente, etc.).

Ce que je voudrais essayer est la suivante. Après l'envoi de toutes vos données d'appel socket.arrêt(ÉCRITURE) (ceci enverra FIN de paquet à l'autre partie) et de ne pas fermer le socket encore. Alors continuez à lire dans le socket jusqu'à ce que vous recevez indication que la connexion est fermée par l'autre extrémité (en C qui est généralement indiqué par 0-longueur read()). Après réception de cette indication, fermer le socket. Lire plus à ce sujet ici.

TCP_NODELAY & TCP_CORK

Si vous êtes l'élaboration de toute sorte de serveur de réseau, vous devez étudier ces options car elles affectent les performances. Sans l'aide de ceux-ci, vous risquez de rencontrer ~20ms retards (Nagle retard) sur chaque paquet envoyé plus de. Bien que ces retards look petites, elles peuvent nuire à vos demandes par seconde statistiques. Une bonne lecture de ce sujet, c'est ici.

Une autre bonne référence à lire sur les sockets est ici.

Sur FastCGI

Je suis d'accord avec les autres intervenants à l'aide de protocole FastCGI pour votre backend peut-être pas une très bonne idée. Si vous vous souciez de performances, alors vous devez mettre en place votre propre nginx module (ou, si cela vous semble trop difficile, un module pour un autre serveur comme NXWEB). Sinon, utiliser le protocole HTTP. Il est plus facile à mettre en œuvre et est beaucoup plus polyvalent que FastCGI. Et je ne dirais pas que HTTP est beaucoup plus lent que FastCGI.

0voto

LarsB Points 445

Bonjour simendsjo,

Les suggestions suivantes peuvent être complètement à côté de la cible.

J'utilise NginX moi-même à des fins de développement; cependant, je ne suis absolument pas un expert sur NginX.

NginX Travailleurs

Néanmoins, votre problème ramené à la mémoire de quelque chose sur les travailleurs et les processus de travail dans NginX.

Entre autres choses, les travailleurs et les processus de travail dans NginX, sont utilisés pour diminuer les temps de latence lorsque les travailleurs blockend sur le disque I/O et de limiter le nombre de connexions par processus lorsque select()/poll() est utilisé.

Vous pouvez trouver plus d'info ici.

NginX Fcgiwrap et de la prise

Un autre pointeur peut être le code suivant, bien que cet exemple est spécifique à Debian.

#!/usr/bin/perl

use strict;
use warnings FATAL => qw( all );

use IO::Socket::UNIX;

my $bin_path = '/usr/local/bin/fcgiwrap';
my $socket_path = $ARGV[0] || '/tmp/cgi.sock';
my $num_children = $ARGV[1] || 1;

close STDIN;

unlink $socket_path;
my $socket = IO::Socket::UNIX->new(
    Local => $socket_path,
    Listen => 100,
);

die "Cannot create socket at $socket_path: $!\n" unless $socket;

for (1 .. $num_children) {
    my $pid = fork;
    die "Cannot fork: $!" unless defined $pid;
    next if $pid;

    exec $bin_path;
    die "Failed to exec $bin_path: $!\n";
}

Vous pouvez trouver plus d'informations sur cette solution ici.

0voto

Peter Postma Points 41

Définissez le délai d'expiration du socket aussi bas que possible, puis fermez le socket. Si vous essayez d'écrire quoi que ce soit sur le socket après cela, que se passe-t-il? Il est possible de pousser un binaire non échappé pour signaler une connexion étroite, le forçant à se terminer. Voilà comment IE est devenu Internet Exploder

0voto

XTF Points 328

AFAIK, il n'est pas nécessaire d'appeler l'arrêt avant la fermeture. L'état TIME_WAIT (de netstat, je suppose?) Ne signifie pas que la connexion n'est pas fermée. Quel est le vrai problème? Vous avez des messages d'erreur des journaux nginx? Avez-vous essayé d'utiliser strace pour découvrir ce que fait nginx?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X