2009-05-26 7 views
9

Les serveurs web non-forking (alias single-threaded ou select() -based) tels que lighttpd ou nginx ont de plus en plus de popularité en .Comment fonctionne un serveur Web non-forking?

Bien qu'il existe une multitude de documents expliquant les serveurs de forking (à différents niveaux de détail), la documentation pour les serveurs non-forking est clairsemée.

Je cherche une vue des yeux d'oiseaux de comment un serveur web non bifurquer fonctionne. (Pseudo-) code ou un diagramme de la machine d'état, dénudé au minimum serait formidable.

Je connais les ressources suivantes et les a trouvées utiles.

Cependant, je suis intéressé par les principes, pas de détails de mise en œuvre.

Plus précisément:

  • Pourquoi ce type de serveur parfois appelé non-blocage, lorsque select() essentiellement des blocs?

  • Le traitement d'une requête peut prendre un certain temps. Que se passe-t-il avec les nouvelles demandes pendant cette période lorsqu'il n'y a pas de thread ou de processus d'écoute spécifique? Le traitement de la demande est-il interrompu ou le temps est-il coupé?

Edit: Si je comprends bien, alors qu'une demande est traitée (fichier de lecture ou exécution par exemple script CGI) le serveur ne peut pas accepter de nouvelles connexions. Cela ne signifie-t-il pas qu'un tel serveur pourrait manquer beaucoup de nouvelles connexions si un script CGI fonctionne, disons, 2 secondes environ?

+1

Je pense qu'un serveur Web non-bifurquer serait un mauvais match à tout serveur Web qui voulait serveur plus qu'une quantité négligeable de contenu dynamique . – Eddie

+0

@Eddie Pas le moins du monde. Avec n processeurs, avoir plus de n threads ne va pas vous permettre de faire plus de travail. Un serveur asynchrone correctement conçu peut faire autant de travail qu'un forking ou un thread. –

+0

@Nick Johnson: Cela dépend. Si vous avez N processeurs et N threads, dans la mesure où une seule requête bloque l'attente d'E/S, vous n'utilisez pas votre processeur à moins de créer plusieurs threads. Par exemple, si vous devez accéder à la base de données pour satisfaire une requête dynamique, ce thread est arrêté jusqu'à ce que vous obteniez une réponse. Avec seulement N threads, vous pouvez passer le plus clair de votre temps à attendre et seulement une petite partie de votre temps de traitement. – Eddie

Répondre

8

pseudocode de base:

setup 
while true 
    select/poll/kqueue 
    with fd needing action do 
     read/write fd 
     if fd was read and well formed request in buffer 
      service request 
     other stuff 
  • Bien que select() & amis bloc, prise E/S ne bloque pas. Vous êtes seulement bloqué jusqu'à ce que vous ayez quelque chose d'amusant à faire.
  • Le traitement de requêtes individuelles impliquait normalement la lecture d'un descripteur de fichier à partir d'un fichier (ressource statique) ou d'un processus (ressource dynamique), puis l'écriture dans le socket. Cela peut être fait facilement sans garder beaucoup d'état.
  • Donc, service request ci-dessus signifie généralement ouvrir un fichier, l'ajouter à la liste pour select, et noter que les choses lues à partir de là vont à un certain socket. Remplacer FastCGI pour le fichier le cas échéant.

EDIT:

  • Je ne sais pas sur les autres, mais nginx a 2 processus: un maître et un travailleur. Le maître écoute et transmet la connexion acceptée au travailleur pour traitement.
4

select() PLUS non bloquante I/O essentiellement permet de gérer/répondre à connexions multiples comme ils viennent en un seul fil (multiplexage), au lieu d'avoir plusieurs threads/processus gérer une prise chacun. L'objectif est de minimiser le rapport entre l'empreinte du serveur et le nombre de connexions.

Il est efficace car ce thread unique tire parti du niveau élevé de connexions socket actives requises pour atteindre la saturation (puisque nous pouvons faire des E/S non bloquantes à plusieurs descripteurs de fichiers).

La logique est qu'il faut très peu de temps pour reconnaître les octets disponibles, les interpréter, puis décider des octets appropriés à mettre dans le flux de sortie. Le travail d'E/S réel est géré sans bloquer ce thread de serveur.

Ce type de serveur attend toujours une connexion, en bloquant sur select(). Une fois qu'il en obtient un, il gère la connexion, puis revisite le select() dans une boucle infinie. Dans le cas le plus simple, ce thread de serveur ne bloque pas d'autres moments en dehors de la configuration des E/S.

S'il y a une deuxième connexion, celle-ci sera traitée à la prochaine sélection du serveur(). À ce stade, la première connexion peut encore recevoir, et nous pouvons commencer à envoyer à la deuxième connexion, à partir du même thread de serveur. C'est le but.

Rechercher "multiplexing network sockets" pour obtenir des ressources supplémentaires.

Ou essayez Unix Network Programming par Stevens, Fenner, Rudoff

Questions connexes