Fermer

juin 13, 2018

Apache vs Nginx Performance: Techniques d'optimisation –20 minutes de lecture

Comment réparer les problèmes de connexion Magento avec des cookies et des sessions - SitePoint


Il y a quelques années, le serveur web de la Fondation Apache, connu sous le nom de "Apache", était si omniprésent qu'il est devenu synonyme de "serveur web". Son processus de démon sur les systèmes Linux porte le nom httpd (signifiant simplement processus HTTP ) – et est préinstallé dans les principales distributions Linux.

Il a été initialement publié en 1995, et, à cite Wikipedia "il a joué un rôle clé dans la croissance initiale du World Wide Web" . C'est toujours le logiciel de serveur web le plus utilisé d'après W3techs . Cependant, selon ces rapports qui montrent certaines tendances de la dernière décennie et des comparaisons avec d'autres solutions sa part de marché diminue. Les rapports donnés par Netcraft et Builtwith diffèrent un peu, mais tous s'accordent sur une baisse tendancielle de la part de marché d'Apache et la croissance de Nginx.

Nginx – prononcé engine x – a été publié en 2004 par Igor Sysoev avec l'intention explicite de surpasser Apache. Le site Web de Nginx a un article qui mérite d'être lu qui compare ces deux technologies. Au début, il était principalement utilisé comme un complément à Apache, principalement pour servir des fichiers statiques, mais il n'a cessé de croître, car il a évolué pour faire face à l'ensemble des tâches du serveur Web.

un reverse proxy équilibreur de charge et cache HTTP . CDN et les fournisseurs de streaming vidéo l'utilisent pour construire leurs systèmes de livraison de contenu où la performance est critique.

Apache existe depuis longtemps, et il a un grand choix de modules . La gestion des serveurs Apache est connue pour être conviviale. Le chargement de module dynamique permet de compiler et d'ajouter différents modules à la pile Apache sans recompiler le binaire du serveur principal. Souvent, les modules seront dans des dépôts de distributions Linux, et après les avoir installés via les gestionnaires de paquets du système, ils peuvent être ajoutés avec élégance à la pile avec des commandes comme a2enmod . Ce genre de flexibilité n'a pas encore été vu avec Nginx. Quand on regarde un guide pour configurer Nginx pour HTTP / 2 les modules sont quelque chose que Nginx doit être construit – configuré pour au moment de la construction.

Une autre fonctionnalité qui a contribué au marché d'Apache La règle est le fichier .htaccess . C'est la solution miracle d'Apache, qui en a fait une solution incontournable pour les environnements d'hébergement partagés, car elle permet de contrôler la configuration du serveur au niveau du répertoire. Chaque répertoire sur un serveur servi par Apache peut avoir son propre fichier .htaccess .

Nginx n'a pas seulement une solution équivalente, mais décourage un tel usage en raison de hits de performance. [19659004]  Statistiques de partage de serveurs, par Netcraft

Parts de marché des fournisseurs de serveurs 1995-2005. Data par Netcraft

LiteSpeed ​​ou LSWS, est un serveur concurrent qui a un niveau de flexibilité comparable à Apache, sans pour autant sacrifier les performances. Il prend en charge Apache-style .htaccess mod_security et mod_rewrite et il vaut la peine d'envisager pour les configurations partagées. Il a été planifié comme remplacement pour Apache et fonctionne avec cPanel et Plesk. Il supporte HTTP / 2 depuis 2015.

LiteSpeed ​​a trois niveaux de licence OpenLiteSpeed, LSWS Standard et LSWS Enterprise. Standard et Enterprise sont livrés avec une solution de mise en cache optionnelle comparable à Varnish, LSCache, qui est intégrée au serveur lui-même et peut être contrôlée, avec des règles de réécriture, dans .htaccess fichiers (par répertoire). Il est également livré avec quelques "batteries" atténuantes DDOS construites en . Cela, avec son architecture événementielle, en fait un concurrent sérieux, ciblant principalement les fournisseurs d'hébergement orientés vers la performance mais cela pourrait valoir la peine d'être mis en place même pour des serveurs ou des sites Web plus petits.

19659013] Lors de l'optimisation de notre système, nous ne pouvons pas insister suffisamment sur l'attention accordée à notre configuration matérielle. Quelle que soit la solution que nous choisissons pour notre installation, avoir suffisamment de RAM est critique. Lorsqu'un processus de serveur Web, ou un interpréteur comme PHP, n'a pas assez de RAM, ils commencent à échanger, et l'échange efficace signifie utiliser le disque dur pour compléter la mémoire RAM. L'effet de ceci est une latence accrue chaque fois que cette mémoire est accédée. Cela nous amène au deuxième point – l'espace du disque dur. L'utilisation du stockage SSD rapide est un autre facteur critique de la rapidité de notre site Web. Nous devons également prendre en compte la disponibilité du processeur et la distance physique entre les centres de données de notre serveur et notre public cible.

Pour approfondir le côté matériel du réglage des performances, Dropbox a un bon article .

Surveillance

Un moyen pratique de surveiller en détail les performances de notre pile de serveurs, par processus, est htop qui fonctionne sous Linux, Unix et macOS, et donne un aperçu coloré de nos processus

 HTOP

D'autres outils de surveillance sont New Relic une solution premium avec un ensemble complet d'outils, et Netdata un open-source solution qui offre une grande extensibilité, des mesures précises et un tableau de bord Web personnalisable, adapté à la fois aux petits systèmes VPS et à la surveillance d'un réseau de serveurs. Il peut envoyer des alarmes pour n'importe quelle application ou processus système par e-mail, Slack, pushbullet, Telegram, Twilio etc.

 Tableau de bord Netdata

Monit est un autre, sans tête, ouvert- outil source qui peut surveiller le système, et peut être configuré pour nous alerter, ou redémarrer certains processus, ou redémarrer le système lorsque certaines conditions sont remplies.

Test du système

AB – Apache Benchmark – est un simple outil de test de charge par Apache Foundation, et Siege est un autre programme de tests de charge. Cet article explique comment les poser tous les deux, et ici nous avons quelques astuces plus avancées pour AB, alors qu'un regard en profondeur sur Siege peut être trouvé ici

Si vous préférez une interface web, il y a Locust un outil basé sur Python qui est très pratique pour tester les performances d'un site Web.

 Installation de criquets [19659004] Après avoir installé Locust, nous devons créer un locustfile dans le répertoire à partir duquel nous allons le lancer:

 from locust import HttpLocust, TaskSet, task

class UserBehavior (TaskSet):
    @tache 1)
    def indice (auto):
        self.client.get ("/")

    @task (2)
    def boutique (auto):
        self.client.get ("/? page_id = 5")

    @task (3)
    page de déf. (auto):
        self.client.get ("/? page_id = 2")

class WebsiteUser (HttpLocust):
    task_set = UserBehavior
    min_wait = 300
    max_wait = 3000

Ensuite, il suffit de le lancer à partir de la ligne de commande:

 locust --host = https: //my-website.com

Un avertissement avec ces outils de test de charge: ils ont l'effet d'une attaque DDoS, il est donc recommandé de limiter les tests à vos propres sites Web.

Tuning Apache

Modules Appm d'Apache

Apache date de 1995 et les premiers jours de l'Internet, quand un moyen accepté pour les serveurs de fonctionner était de générer un nouveau processus sur chaque connexion TCP entrante et d'y répondre. Si davantage de connexions sont entrées, davantage de processus de travail ont été créés pour les gérer. Le coût de la génération de nouveaux processus était élevé, et les développeurs d'Apache ont conçu un mode prefork avec un nombre de processus pré-spawned. Les interpréteurs de langage dynamiques incorporés dans chaque processus (comme mod_php ) étaient encore coûteux, et les plantages du serveur avec les configurations par défaut d'Apache sont devenus courants. Chaque processus n'était capable de gérer qu'une seule connexion entrante.

Ce modèle est connu sous le nom de mpm_prefork_module dans le système MPM (Multi-Processing Module) d'Apache. Selon le site web d'Apache ce mode nécessite peu de configuration, car il est autorégulé, et le plus important est que la directive MaxRequestWorkers soit suffisamment grande pour gérer autant de demandes simultanées comme vous prévoyez de recevoir, mais assez petit pour assurer qu'il y ait assez de RAM physique pour tous les processus

 libapache2-mod-php7 mpm_prefork Rapport HTOP

Un petit test de charge acridienne cela montre la génération d'un grand nombre de processus Apache pour gérer le trafic entrant.

Nous pouvons ajouter que ce mode est peut-être la plus grande cause de la mauvaise réputation d'Apache. Il peut devenir inefficace en ressources.

La version 2 d'Apache a apporté deux autres MPM qui tentent de résoudre les problèmes que le mode prefork a. Ce sont module de travail ou mpm_worker_module et module d'événement .

Le module travailleur n'est plus basé sur des processus; C'est un mode de fonctionnement hybride basé sur le processus. Citant le site Web d'Apache

un seul processus de contrôle (le parent) est responsable du lancement des processus fils. Chaque processus enfant crée un nombre fixe de threads de serveur comme spécifié dans la directive ThreadsPerChild ainsi qu'un thread d'écoute qui écoute les connexions et les transmet à un thread de serveur pour traitement lorsqu'elles arrivent. le mode est plus économe en ressources.

La version 2.4 d'Apache nous a apporté le troisième module d'événement MPM – . Il est basé sur MPM, et a ajouté un thread d'écoute séparé qui gère les connexions keepalive dormantes une fois la requête HTTP terminée. C'est un mode asynchrone non bloquant avec une empreinte mémoire plus petite. En savoir plus sur les améliorations de la version 2.4 ici .

Nous avons chargé une installation de test WooCommerce avec environ 1200 messages sur un serveur virtuel et testé sur Apache 2.4 avec le mode par défaut, prefork et mod_php. D'abord, nous l'avons testé avec libapache2-mod-php7 et mpm_prefork_module à https://tools.pingdom.com:

mpm prefork test

Ensuite, nous sommes allés faire des tests l'événement module MPM.

Nous avons dû ajouter multiverse à notre /etc/apt/sources.list :

 deb http://archive.ubuntu.com/ ubuntu xenial principal restreint univers multiverse
deb http://archive.ubuntu.com/ubuntu xenial-updates principal restreint univers multiverse
deb http://security.ubuntu.com/ubuntu xenial-security principal univers restreint multiverse
deb http://archive.canonical.com/ubuntu partenaire xenial

Puis nous avons fait sudo apt-get mise à jour et installé libapache2-mod-fastcgi et php-fpm:

 sudo apt-get install libapache2-mod-fastcgi php7. 0-fpm

Comme php-fpm est un service distinct d'Apache, il fallait le redémarrer:

 sudo service start php7.0-fpm

Puis nous avons désactivé le module prefork, et activé le mode événement et proxy_fcgi:

 sudo a2dismod php7.0 mpm_prefork
sudo a2enmod mpm_event proxy_fcgi

Nous avons ajouté cet extrait à notre hôte virtuel Apache:

 & lt; filesmatch " .php $" & gt;
    SetHandler "proxy: fcgi: //127.0.0.1: 9000 /"
& lt; / filesmatch & gt;

Ce port doit être compatible avec la configuration de php-fpm dans /etc/php/7.0/fpm/pool.d/www.conf . Pour en savoir plus sur l'installation de php-fpm ici .

Puis nous avons réglé la configuration de mpm_event dans /etc/apache2/mods-available/mpm_event.conf en gardant à l'esprit que notre mini Les ressources de -VPS pour ce test étaient limitées – nous avons simplement réduit certains nombres par défaut. Détails sur chaque directive sur le site Web d'Apache et astuces spécifiques à l'événement mpm ici . Gardez à l'esprit que les serveurs ont commencé à consommer une quantité de mémoire, peu importe leur niveau d'activité. La directive MaxRequestWorkers définit la limite du nombre de requêtes simultanées autorisées: il est important de définir MaxConnectionsPerChild sur une valeur autre que zéro, car cela prévient une éventuelle fuite de mémoire.

 
        StartServers 1
        MinSpareThreads 30
        MaxSpareThreads 75
        ThreadLimit 64
        ThreadsPerChild 30
        MaxRequestWorkers 80
        MaxConnectionsPerChild 80

Puis nous avons redémarré le serveur avec sudo service apache2 restart (si nous changeons certaines directives, comme ThreadLimit, nous devrons arrêter et démarrer le service explicitement, avec sudo service apache2 stop; service apache2 start ).

Nos tests sur Pingdom montrent maintenant un temps de chargement réduit de plus de la moitié:

 Pingdom test

Autres astuces pour le réglage Apache: [19659033] Désactivation de .htaccess : htaccess permet de définir une configuration spécifique pour chaque répertoire de notre racine de serveur, sans redémarrer. Donc, parcourir tous les répertoires, rechercher les fichiers .htaccess, à chaque requête, entraîne une pénalité de performance.

Citation des docs Apache:

En général, vous ne devriez utiliser que .htaccess fichiers lorsque vous n'avez pas accès au fichier de configuration du serveur principal. *
… en général, l'utilisation des fichiers .htaccess doit être évitée autant que possible. N'importe quelle configuration que vous considérez mettre dans un fichier .htaccess peut tout aussi bien être faite dans une section dans votre fichier de configuration du serveur principal. *

La ​​solution est de le désactiver dans /etc/apache2/apache2.conf :

 AllowOverride Aucun

Si nous en avons besoin pour les répertoires spécifiques, nous pouvons alors l'activer dans les sections de nos fichiers hôtes virtuels:

 AllowOverride All

Autres astuces:

  • Contrôler le cache du navigateur avec mod_expires – en définissant les en-têtes expires

  • Conserver HostNameLookups désactivé – HostNameLookups Off est le par défaut depuis Apache 1.3, mais assurez-vous qu'il reste désactivé, car il peut entraîner une pénalité de performance.

  • Apache2buddy est un script simple que nous pouvons exécuter et obtenir des conseils pour régler notre système: curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl

 apache2buddy

Nginx

Nginx est un serveur web piloté par les événements et non bloquant. Pour citer une affiche sur Hacker News

Les processus de forking sont incroyablement coûteux par rapport à une boucle d'événement. Les serveurs HTTP basés sur des événements ont inévitablement gagné.

Cette déclaration a suscité un débat sur Hacker News, mais d'après notre expérience, le simple fait de passer d'un Apache mpm_prefork à Nginx peut souvent empêcher le site de se bloquer. Le simple passage à Nginx est très souvent un remède en lui-même

 Nginx architecture

Une explication visuelle plus complète de l'architecture Nginx peut être trouvée ici .

Nginx recommande d'épingler le nombre de travailleurs au nombre de cœurs de PC (comme nous l'avons fait avec la configuration mpm_event d'Apache), en mettant worker_processes à auto (par défaut 1) dans /etc/nginx/nginx.conf .

worker_connections définit le nombre de connexions que chaque processus de travail peut gérer. La valeur par défaut est 512, mais elle peut généralement être augmentée.

Les connexions persistantes sont un aspect du serveur qui affecte les performances, ce qui n'est généralement pas visible dans les tests de performances .  keepalive.cf

Selon le site Web Nginx

Les connexions HTTP keepalive sont une fonction de performance nécessaire qui réduit la latence et permet aux pages Web de se charger plus rapidement.

Les connexions TCP peuvent être coûteuses – sans parler du cryptage HTTPS . Le protocole HTTP / 2 atténue ce problème avec ses fonctions de multiplexage . Réutiliser une connexion existante peut réduire les temps de requête.

mpm_prefork et mpm_worker d'Apache souffrent de limitations de concurrence qui contrastent avec la boucle d'événement keepalive. Ceci est quelque peu corrigé dans Apache 2.4, dans le module mpm_event, et est le seul mode de fonctionnement par défaut dans Nginx. Nginx peut gérer des milliers de connexions entrantes simultanément, et s'il est utilisé comme proxy inverse ou équilibreur de charge, Nginx utilise alors un pool local de connexions keepalive, sans surcharge de connexion TCP.

keepalive_requests [19659102]
keepalive_timeout définit l'heure à laquelle une connexion keepalive inactive reste ouverte.

keepalive est un paramètre relatif à une connexion Nginx à un serveur en amont - lorsqu'il agit en tant que proxy ou équilibreur de charge. Cela signifie le nombre de connexions amont keepalive inactives par processus de travail.

L'activation des connexions keepalive en amont nécessite la mise en place de ces directives dans la configuration principale de Nginx:

 proxy_http_version 1.1;
proxy_set_header Connexion "";

Les connexions en amont Nginx sont gérées par ngx_http_upstream_module .

Si notre application frontale continue d'interroger notre application dorsale pour les mises à jour, augmente les keepalive_requests et keepalive_timeout limitera le nombre de connexions à établir. La directive keepalive ne doit pas être trop grande, pour permettre aux autres connexions d'atteindre notre serveur en amont.

L'ajustement de ces paramètres est effectué au cas par cas et doit être testé. C'est peut-être une raison pour laquelle keepalive n'a pas de paramètre par défaut

Utiliser unix sockets

Par défaut, Nginx utilise un processus PHP séparé auquel il transmet les demandes de fichiers PHP. Dans ce cas, il agit comme un proxy (tout comme Apache quand nous l'avons configuré avec php7.0-fpm).

Souvent notre configuration d'hôte virtuel avec Nginx ressemblera à ceci:

 location ~  .php $ {
    fastcgi_param REQUEST_METHOD $ request_method;
    fastcgi_param SCRIPT_FILENAME $ racine_document $ fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;
}

Comme FastCGI est un protocole différent de HTTP, les deux premières lignes transmettent certains arguments et en-têtes à php-fpm, tandis que la troisième ligne spécifie le moyen de proxy de notre requête - sur un socket réseau local.

pratique pour les configurations multi-serveurs, puisque nous pouvons aussi spécifier des serveurs distants aux requêtes proxy.

Mais si nous hébergeons notre installation entière sur un seul système, nous devrions utiliser un socket Unix pour se connecter au processus php d'écoute:

 fastcgi_pass unix: /var/run/php7.0-fpm.sock;

Les sockets Unix sont considérés comme ayant de meilleures performances que TCP et cette configuration est considérée comme plus sûre. Vous pouvez trouver plus de détails sur cette configuration dans cet article de Rackspace .

Cette astuce concernant les sockets Unix est également applicable pour Apache. Plus de détails ici .

gzip_static : la sagesse acceptée autour des performances du serveur web est de compresser nos ressources statiques. Cela signifie souvent que nous essaierons de faire des compromis et d'essayer de ne compresser que les fichiers dépassant certains seuils, car la compression des ressources à la volée, à chaque requête, peut s'avérer coûteuse. Nginx a une directive gzip_static qui nous permet de servir des versions gzippées de fichiers - avec l'extension .gz - au lieu des ressources habituelles:

 location / assets {
    gzip_static activé;
}

De cette façon, Nginx va essayer de servir style.css.gz au lieu de style.css (nous devons nous occuper du gzipping nous-mêmes, dans ce cas). De cette façon, les cycles du processeur ne seront pas gaspillés par la compression à la volée pour chaque requête.

Mise en cache avec Nginx

L'histoire de Nginx ne serait pas complète sans mentionner comment mettre en cache le contenu. La mise en cache de Nginx est si efficace que de nombreux administrateurs système ne pensent pas que des couches séparées pour mise en cache HTTP - comme Varnish - ont beaucoup de sens. Peut-être est-il moins élaboré, mais la simplicité est une caractéristique . L'activation de la mise en cache avec Nginx est plutôt simple.

 proxy_cache_path / chemin / vers / cache niveaux = 1: 2 keys_zone = my_cache: 10m max_size = 10g
  inactif = 60m;

Il s'agit d'une directive que nous plaçons dans notre fichier hôte virtuel, en dehors du du bloc server . L'argument proxy_cache_path peut être n'importe quel chemin que nous voulons stocker notre cache. niveaux désigne le nombre de niveaux de répertoires dans lesquels Nginx doit stocker le contenu mis en cache. Pour des raisons de performances, deux niveaux sont généralement acceptables. Récursif à travers les répertoires peut être coûteux. L'argument keys_zone est un nom pour une zone de mémoire partagée utilisée pour stocker les clés de cache, et 10m est la place pour ces clés en mémoire (10MB est généralement suffisant, ce n'est pas le pièce pour le contenu mis en cache réel). max_size est facultatif et définit la limite supérieure pour le contenu mis en cache - ici 10GB. Si ce n'est pas spécifié, il prendra tout l'espace disponible. inactive spécifie combien de temps le contenu peut rester dans le cache sans être demandé, avant qu'il ne soit supprimé par Nginx.

Après avoir configuré ceci, nous ajouterons la ligne suivante, avec le nom de notre zone mémoire soit serveur ou emplacement bloquer:

 proxy_cache my_cache;

Une couche supplémentaire de tolérance aux pannes avec Nginx peut être obtenue en lui indiquant de servir les éléments du cache lorsqu'il rencontre une erreur de serveur sur l'origine, le serveur en amont ou lorsque le serveur est hors service:

 proxy_cache_use_stale erreur timeout http_500 http_502 http_503 http_504;

Plus de détails sur le serveur ou le emplacement des instructions de bloc pour affiner la mise en cache de Nginx peuvent être trouvés ici

proxy_cache _ * [19459027LesdirectivessontpourlesactifsstatiquesmaisnousvoulonsgénéralementmettreencachelasortiedynamiquedenosapplicationsWeb-quecesoitunCMSouautrechoseDanscecasnousutiliseronsladirective fastcgi_cache _ * au lieu de proxy_cache _ * :

 fastcgi_cache_path / var / run / nginx-cache niveaux = 1: 2 keys_zone = mon_cache: 10m inactif = 60m;
 fastcgi_cache_key "$ scheme $ request_method $ hôte $ request_uri";
 fastcgi_cache_use_stale erreur timeout invalid_header http_500;
 fastcgi_ignore_headers Cache-Control expire Set-Cookie;
 add_header NGINX_FASTCGI_CACHE $ upstream_cache_status;

La dernière ligne ci-dessus définira les en-têtes de réponse pour nous informer si le contenu a été fourni par le cache ou non

Ensuite, dans notre serveur ou bloc d'emplacement, nous pouvons définir des exceptions à la mise en cache. La chaîne de requête est présente dans l'URL de la demande:

 if ($ query_string! = "") {
    mettre $ skip_cache 1;
}

Aussi, dans notre bloc . Php à l'intérieur du server dans le cas de PHP, nous ajouterions quelque chose comme:

 location ~  .php $ {
    try_files $ uri = 404;
    inclure fastcgi_params;

    fastcgi_read_timeout 360s;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_param SCRIPT_FILENAME $ racine_document $ fastcgi_script_name;

    fastcgi_pass unix: /run/php/php7.0-fpm.sock;

      fastcgi_index index.php;
      fastcgi_cache_bypass $ skip_cache;
      fastcgi_no_cache $ skip_cache;
      fastcgi_cache my_cache;
      fastcgi_cache_valid 60m;
}

Ci-dessus, les lignes fastcgi_cache * et fastcgi_no_cache règlent la mise en cache et les exclusions
Référence détaillée de toutes ces directives sur le site Nginx docs

Pour en savoir plus, les personnes de Nginx ont fourni un webinaire gratuit sur ce sujet, et un nombre de livres électroniques est disponible.

Conclusion [19659013] Nous avons essayé d'introduire quelques techniques qui nous aideront à améliorer les performances de notre serveur web, et la théorie derrière ces techniques. Mais ce sujet n'est en aucun cas épuisé: nous n'avons toujours pas couvert les configurations de proxy inverse qui consistent à la fois en Apache et en Nginx, ou en configurations multi-serveurs. Atteindre les meilleurs résultats avec ces deux serveurs est une question de test et d'analyse de cas concrets spécifiques. C'est un sujet sans fin.



Source link