web-dev-qa-db-fra.com

Ruby sur Rails Options du serveur

Toute la question de la configuration d’un serveur de développement pour mon application Ruby sur Rails me perturbe. Il y a WEBrick, Mongrel, Passenger, Apache, Nginx et bien d'autres, j'en suis sûr, et je ne comprends pas vraiment les différents rôles qu'ils jouent.

J'ai commencé à utiliser WEBrick et maintenant j'utilise Mongrel pour le développement. Ces serveurs sont-ils autonomes ou sont-ils assis devant Apache?

J'ai lu sur Passenger et je ne comprends pas vraiment ce que c'est. Le site indique que "le déploiement de Ruby applications Web devient un jeu d'enfant", remplace-t-il Mongrel? Est-ce que c'est comme Capistrano, qui déploie aussi des applications web?

Gardant à l'esprit que je voudrais tester SSL, et je pense que ce n'est pas supporté par mongrel, quelle est la meilleure configuration de serveur de développement?

Merci

571
pingu

Le mot "déploiement" peut avoir deux significations selon le contexte. Vous confondez également les rôles d’Apache/Nginx avec ceux d’autres composants.

Remarque historique: cet article a été rédigé le 6 novembre 2010, lorsque l'écosystème du serveur d'applications Ruby était limité. J'ai mis à jour cet article le 15 mars 2013 avec toutes les dernières mises à jour de l'écosystème.

Disclaimer : Je suis l'un des auteurs de Phusion Passenger, l'un des serveurs de l'application.

Apache vs Nginx

Ils sont tous deux serveurs Web. Ils peuvent servir des fichiers statiques mais - avec les bons modules - peuvent également servir des applications Web dynamiques, par exemple. ceux écrits en PHP. Apache est plus populaire et a plus de fonctionnalités, Nginx est plus petit et plus rapide et a moins de fonctionnalités.

Ni Apache ni Nginx ne peuvent servir Ruby d'applications Web prêtes à l'emploi. Pour ce faire, vous devez utiliser Apache/Nginx en combinaison avec un type de module complémentaire, décrit plus loin.

Apache et Nginx peuvent également agir en tant que proxys inversés, ce qui signifie qu’ils peuvent prendre une requête HTTP entrante et la transmettre à un autre serveur, qui parle également HTTP. Lorsque ce serveur répond avec une réponse HTTP, Apache/Nginx renvoie la réponse au client. Vous apprendrez plus tard pourquoi c'est pertinent.

Mongrel et autres serveurs d'applications de production contre WEBrick

Mongrel est un Ruby "serveur d'application": Concrètement, cela signifie que Mongrel est une application qui:

  1. Charge votre application Ruby dans son propre espace de processus.
  2. Configure un socket TCP, lui permettant de communiquer avec le monde extérieur (par exemple, Internet). Mongrel écoute les requêtes HTTP sur ce socket et transmet les données de la requête à l'application Web Ruby.
  3. L'application Web Ruby retourne ensuite un objet, qui décrit à quoi devrait ressembler la réponse HTTP, et Mongrel se charge de la convertir en une réponse HTTP réelle (les octets réels) et de la renvoyer via le socket.

Cependant, Mongrel est assez démodé, il n’est plus maintenu. Les nouveaux serveurs d'applications alternatifs sont:

  • Phusion Passenger
  • Licorne
  • Mince
  • Puma
  • Trinidad (JRuby seulement)
  • TorqueBox (JRuby uniquement)

Je les couvrirai plus tard et décrirai en quoi elles diffèrent les unes des autres et de Mongrel.

WEBrick fait la même chose que Mongrel, mais les différences sont les suivantes:

  • WEBrick n'est pas adapté à la production, contrairement à tout ce que j'ai déjà mentionné. WEBrick est entièrement écrit en Ruby. Mongrel (et la plupart des autres serveurs d'applications Ruby) fait partie des parties Ruby et C (principalement Ruby), mais son analyseur HTTP est écrit en C pour améliorer les performances.
  • WEBrick est plus lent et moins robuste. Il y a des fuites de mémoire connues et des problèmes d'analyse HTTP connus.
  • WEBrick est généralement utilisé uniquement comme serveur par défaut lors du développement, car WEBrick est inclus dans Ruby par défaut. Mongrel et les autres serveurs d'applications doivent être installés séparément. Il n'est pas recommandé d'utiliser WEBrick dans des environnements de production. Cependant, Heroku a choisi WEBrick comme serveur par défaut. Ils utilisaient déjà Thin auparavant, je ne vois donc pas pourquoi ils sont passés à WEBrick.

Le serveur d'applications et le monde

Tous les serveurs d'applications actuels Ruby parlent HTTP. Toutefois, certains serveurs d'applications peuvent être directement exposés à Internet sur le port 80, alors que d'autres ne le peuvent pas.

  • Serveurs d'applications pouvant être directement exposés à Internet: Phusion Passenger, Rainbows
  • Serveurs d'applications susceptibles de ne pas être directement exposés à Internet: Mongrel, Unicorn, Thin, Puma. Ces serveurs d'applications doivent être placés derrière un serveur Web à proxy inverse comme Apache et Nginx.
  • Je ne connais pas assez Trinidad et TorqueBox, je les ai donc omis.

Pourquoi certains serveurs d'applications doivent-ils être placés derrière un proxy inverse?

  • Certains serveurs d'applications ne peuvent traiter qu'une seule demande simultanément, par processus. Si vous souhaitez gérer deux demandes simultanément, vous devez exécuter plusieurs instances de serveur d'applications, chacune servant la même application Ruby. Cet ensemble de processus de serveur d'applications s'appelle un cluster de serveurs d'applications (d'où le nom Mongrel Cluster, Thin Cluster, etc.). Vous devez ensuite configurer Apache ou Nginx pour inverser le proxy sur ce cluster. Apache/Nginx se chargera de la distribution des requêtes entre les instances du cluster (Plus de détails à ce sujet dans la section "Modèles de simultanéité d'E/S").
  • Le serveur Web peut mettre en mémoire tampon les demandes et les réponses, protégeant ainsi le serveur d'applications des "clients lents", des clients HTTP qui n'envoient ni n'acceptent pas les données très rapidement. Vous ne voulez pas que votre serveur d'applications ne fasse rien en attendant que le client envoie la demande complète ou reçoive la réponse complète, car pendant ce temps, le serveur d'applications ne pourra peut-être rien faire d'autre. Apache et Nginx savent très bien faire beaucoup de choses en même temps, car ils sont multithreads ou eventés.
  • La plupart des serveurs d'applications peuvent servir des fichiers statiques, mais ne sont pas particulièrement doués pour cela. Apache et Nginx peuvent le faire plus rapidement.
  • Généralement, les utilisateurs configurent Apache/Nginx pour traiter directement les fichiers statiques, mais transfèrent les demandes qui ne correspondent pas aux fichiers statiques au serveur d'applications, ce qui est une bonne pratique de sécurité. Apache et Nginx sont très matures et peuvent protéger le serveur d'applications contre les demandes corrompues (peut-être malveillantes).

Pourquoi certains serveurs d'applications peuvent-ils être directement exposés à Internet?

  • Phusion Passenger est une bête très différente de tous les autres serveurs d'applications. L'une de ses caractéristiques uniques est qu'il s'intègre au serveur Web.
  • L'auteur de Rainbows a déclaré publiquement qu'il est sûr de l'exposer directement à Internet. L'auteur est à peu près sûr qu'il n'y a pas de vulnérabilités dans l'analyseur HTTP (et similaire). Néanmoins, l'auteur ne fournit aucune garantie et dit que l'utilisation est à ses risques et périls.

Serveurs d'applications comparés

Dans cette section, je comparerai la plupart des serveurs d'applications que j'ai mentionnés, mais pas Phusion Passenger. Phusion Passenger est une bête si différente du reste que je lui ai donné une section dédiée. J'ai également omis Trinidad et TorqueBox parce que je ne les connais pas assez bien, mais ils ne sont pertinents que de toute façon si vous utilisez JRuby.

  • Mongrel était plutôt squelettique. Comme mentionné précédemment, Mongrel est purement multi-processus mono-thread, il n'est donc utile que dans un cluster. Il n'y a pas de surveillance de processus: si un processus de la grappe se bloque (par exemple à cause d'un bogue dans l'application), il doit être redémarré manuellement. Les gens ont tendance à utiliser des outils externes de surveillance des processus tels que Monit et Dieu.
  • Licorne est une fourchette de bâtard. Il prend en charge la surveillance de processus limitée: si un processus tombe en panne, il est automatiquement redémarré par le processus maître. Cela peut faire en sorte que tous les processus écoutent sur un seul socket partagé, au lieu d'un socket séparé pour chaque processus. Cela simplifie la configuration du proxy inverse. Comme Mongrel, il s’agit de processus multiples purement mono-thread.
  • Thin utilise le modèle d'E/S avec événement en utilisant la bibliothèque EventMachine. Autre que l'utilisation de l'analyseur HTTP Mongrel, il n'est en aucun cas basé sur Mongrel. Son mode cluster n'a pas de surveillance de processus, vous devez donc surveiller les pannes, etc. Il n'y a pas de socket partagé semblable à Unicorn, chaque processus écoute donc sur son propre socket. En théorie, le modèle d'E/S de Thin autorise une grande concurrence, mais dans la plupart des situations pratiques pour lesquelles Thin est utilisé, un processus Thin ne peut gérer qu'une seule demande simultanée. Vous avez donc toujours besoin d'un cluster. Plus d'informations sur cette propriété particulière dans la section "Modèles de concurrence d'accès d'E/S".
  • Puma a également été créé à partir de Mongrel, mais contrairement à Unicorn, Puma est conçu pour être purement multithread. Il n'y a donc actuellement aucun support de cluster intégré. Vous devez faire particulièrement attention à pouvoir utiliser plusieurs cœurs (pour plus d'informations à ce sujet, reportez-vous à la section "Modèles d'accès concurrents d'E/S").
  • Rainbows prend en charge plusieurs modèles de simultanéité via l'utilisation de bibliothèques différentes.

Phusion Passenger

Phusion Passenger fonctionne très différemment de tous les autres. Phusion Passenger s'intègre directement dans Apache ou Nginx, et peut donc être comparé à mod_php pour Apache. Tout comme mod_php permet à Apache de servir des applications PHP, presque comme par magie, Phusion Passenger permet à Apache (ainsi que Nginx!) De servir des applications Ruby, presque comme par magie. Le but de Phusion Passenger est de faire en sorte que tout fonctionne Just Work (tm) avec le moins de tracas possible.

Au lieu de démarrer un processus ou un cluster pour votre application et de configurer Apache/Nginx pour qu'il puisse traiter des fichiers statiques et/ou des requêtes de proxy inverses vers le processus/cluster avec Phusion Passenger, vous devez uniquement:

  1. Vous éditez le fichier de configuration du serveur Web et spécifiez l'emplacement du répertoire "public" de votre Ruby.
  2. Il n'y a pas d'étape 2.

Toute la configuration est effectuée dans le fichier de configuration du serveur Web. Phusion Passenger automatise à peu près tout. Il n'est pas nécessaire de démarrer un cluster et de gérer les processus. Démarrage/arrêt des processus, redémarrage en cas de blocage, etc. - tout est automatisé. Par rapport aux autres serveurs d'applications, Phusion Passenger comporte beaucoup moins de pièces mobiles. Cette facilité d'utilisation est l'une des principales raisons pour lesquelles on utilise Phusion Passenger.

De plus, contrairement aux autres serveurs d'applications, Phusion Passenger est principalement écrit en C++, ce qui le rend très rapide.

Il existe également un variante Entreprise de Phusion Passenger avec encore plus de fonctionnalités, telles que redémarrage automatique par roulement, support multithreading, résistance aux erreurs de déploiement, etc.

Pour les raisons susmentionnées, Phusion Passenger est actuellement le serveur d’application le plus populaire Ruby, alimentant plus de 150 000 sites Web, y compris des sites importants tels que le New York Times, Pixar, Airbnb, etc.

Phusion Passenger vs autres serveurs d'applications

Phusion Passenger fournit beaucoup plus de fonctionnalités et offre de nombreux avantages par rapport aux autres serveurs d'applications, tels que:

  • Ajustement dynamique du nombre de processus en fonction du trafic. Nous exécutons une tonne d'applications Rails sur notre serveur aux ressources limitées, qui ne sont pas destinées au public et que les membres de notre organisation utilisent au maximum quelques fois par jour. Des choses comme Gitlab, Redmine, etc. Phusion Passenger peut ralentir ces processus lorsqu'ils ne sont pas utilisés, et les relancer quand ils sont utilisés, permettant ainsi de disposer de plus de ressources pour des applications plus importantes. Avec d'autres serveurs d'applications, tous vos processus sont activés à tout moment.
  • Certains serveurs d'applications ne sont pas performants à certaines charges de travail, de par leur conception. Par exemple, Unicorn est conçu uniquement pour les requêtes à exécution rapide: Voir le site Web de Unicorn section "Tout simplement pire dans certains cas".

Les charges de travail pour lesquelles Licorne n'est pas bonne sont:

  • Diffusion de charges de travail (par exemple Rails 4 diffusion en direct ou Rails 4 diffusion en continu du modèle).
  • Workloads dans lesquels l'application effectue des appels d'API HTTP.

Le modèle d’E/S hybride de Phusion Passenger Enterprise 4 ou ultérieure en fait un excellent choix pour ce type de charge de travail.

  • D'autres serveurs d'applications nécessitent que l'utilisateur exécute au moins une instance par application. En revanche, Phusion Passenger prend en charge plusieurs applications en une seule instance. Cela réduit considérablement les frais d’administration.
  • Changement automatique d'utilisateur, une fonction de sécurité pratique.
  • Phusion Passenger prend en charge de nombreuses IRM Ruby, JRuby et Rubinius. Mongrel, Unicorn et Thin ne supportent que l'IRM. Puma prend également en charge tous les 3.
  • Phusion Passenger ne supporte pas seulement Ruby! Il prend également en charge Python WSGI, afin de pouvoir par exemple également exécuter des applications Django et Flask. En fait, Phusion Passenger est en train de devenir un serveur polyglotte. Node.js support sur la liste de tâches.
  • Collecte des ordures hors bande. Phusion Passenger peut exécuter le ramasse-miettes Ruby en dehors du cycle normal de demandes/réponses, ce qui réduit potentiellement les temps de demande de plusieurs centaines de millisecondes. Unicorn possède également une fonctionnalité similaire, mais la version de Phusion Passenger est plus flexible car 1) elle ne se limite pas au GC et peut être utilisée pour un travail arbitraire. 2) La version de Phusion Passenger fonctionne bien avec les applications multithread, contrairement à celle de Unicorn.
  • Redémarrage automatique par roulement. Les redémarrages progressifs sur Unicorn et d’autres serveurs nécessitent un travail de script. Phusion Passenger Enterprise automatise complètement cette procédure pour vous.

Il y a plus de fonctionnalités et d'avantages, mais la liste est vraiment longue. Vous devez vous reporter au manuel complet de Phusion Passenger ( version Apache , version de Nginx ) ou site Web de Phusion Passenger pour plus d'informations.

Modèles de simultanéité d'E/S

  • Multi-processus mono-thread. Il s'agit traditionnellement du modèle d'E/S le plus populaire pour les serveurs d'applications Ruby, en partie parce que le support multithreading dans l’écosystème Ruby était très mauvais. Chaque processus peut traiter exactement une demande à la fois. La charge du serveur Web entre les processus. Ce modèle est très robuste et le programmeur a peu de chance d'introduire des bogues d'accès concurrentiel. Cependant, son accès simultané aux E/S est extrêmement limité (limité par le nombre de processus). Ce modèle convient parfaitement aux charges de travail rapides et de courte durée. Il est très inapproprié pour les charges de travail d'E/S bloquantes lentes et longues, par ex. les charges de travail impliquant l’appel d’API HTTP.
  • Purement multithread. De nos jours, l'écosystème Ruby dispose d'un excellent support multithreading, ce modèle d'E/S est donc devenu très viable. Le multithreading autorise une grande concurrence d'accès d'E/S, ce qui le rend adapté aux charges de travail d'E/S bloquantes de courte ou longue durée. Le programmeur est plus susceptible d’introduire des bogues de concurrence, mais heureusement, la plupart des frameworks Web sont conçus de telle sorte que cela reste très improbable. Il convient toutefois de noter que l'interpréteur MRI Ruby ne peut pas exploiter plusieurs cœurs de processeur, même en présence de plusieurs threads, en raison de l'utilisation du verrou d'interprète global (GIL). Vous pouvez contourner ce problème en utilisant plusieurs processus multithreads, car chaque processus peut exploiter un cœur de processeur. JRuby et Rubinius n'ont pas de GIL, ils peuvent donc exploiter pleinement plusieurs cœurs dans un seul processus.
  • Multi-processus hybride multi-thread. Principalement implémenté par Phusion Passenger Enterprise 4 et versions ultérieures. Vous pouvez facilement basculer entre plusieurs processus mono-threadés, purement multithread ou même plusieurs processus, chacun avec plusieurs threads. Ce modèle offre le meilleur des deux mondes.
  • Evented. Ce modèle est complètement différent du modèle mentionné précédemment. Il autorise une très grande concurrence d'accès d'E/S et est donc excellent pour les charges de travail d'E/S bloquantes de longue durée. Pour l'utiliser, un support explicite de l'application et du framework est requis. Cependant, tous les principaux cadres tels que Rails et Sinatra ne prennent pas en charge le code événementiel. C'est pourquoi, dans la pratique, un processus Thin ne peut toujours pas traiter plus d'une demande à la fois, ce qui lui permet de se comporter de la même manière que le modèle à processus multiples à un seul thread. Il existe des infrastructures spécialisées pouvant tirer parti des E/S événementielles, telles que Cramp.

Un article a récemment été publié sur le blog Phusion sur le réglage optimal du nombre de processus et de threads en fonction de votre charge de travail. Voir Réglage des paramètres d'accès simultané de Phusion Passenger .

Capistrano

Capistrano est quelque chose de complètement différent. Dans toutes les sections précédentes, "déploiement" fait référence au fait de lancer votre application Ruby sur un serveur d'applications, de sorte qu'elle devienne accessible aux visiteurs, mais avant que cela ne puisse se produire, vous devez généralement effectuer un travail de préparation. , tel que:

  • Téléchargement du code et des fichiers de l'application Ruby sur la machine serveur.
  • L'installation de bibliothèques sur lesquelles repose votre application.
  • Configuration ou migration de la base de données.
  • Démarrer et arrêter tous les démons sur lesquels votre application pourrait s'appuyer, tels que les travailleurs Sidekiq/Resque ou autre.
  • Toutes les autres tâches à effectuer lors de la configuration de votre application.

Dans le contexte de Capistrano, "déploiement" signifie faire tout ce travail de préparation. Capistrano n'est pas un serveur d'applications. Au lieu de cela, c'est un outil pour automatiser tout ce travail de préparation. Vous indiquez à Capistrano où se trouve votre serveur et quelles commandes doivent être exécutées chaque fois que vous déployez une nouvelle version de votre application. Capistrano se chargera de télécharger l'application Rails sur le serveur et d'exécuter les commandes. vous avez spécifié.

Capistrano est toujours utilisé en combinaison avec un serveur d'applications. Il ne remplace pas les serveurs d'applications. Inversement, les serveurs d'applications ne remplacent pas Capistrano, ils peuvent être utilisés en combinaison avec Capistrano.

Bien sûr, vous n'avez pas avez pour utiliser Capistrano. Si vous préférez télécharger votre application Ruby avec FTP et exécuter manuellement les mêmes étapes de commandes à chaque fois, vous pouvez le faire. D'autres personnes en ont eu assez, alors elles automatisent ces étapes à Capistrano.

1253
Hongli