Formation Apache



Apache, HTTP, performance et plus encore !



VIA Centrale Réseaux

Lothar <lothar [arobase] via.ecp.fr>
13/03/2014

Introduction

Apache, c'est quoi ?




/əˈpætʃiː/    ə-pa-chee


C'est un serveur HTTP !

...

Mais plus encore ?


Serveur web open-source développé par la fondation Apache depuis 1995

Serveur le plus utilisé à travers le monde


Avantages : répandu, très bien documenté, robuste, modulaire, nombreuses fonctionnalités, libre et multiOS

Inconvénients : pas forcément le plus rapide

Apache HTTP vs Fondation Apache


Fondation Apache : Association non lucrative
 Communauté décentralisée de développeurs open-source

Créée initialement (1999) pour soutenir le développement de Apache HTTP Server


Mais bien plus maintenant :
OpenOffice, SVN, Tomcat, Maven,  Ant, Cassandra, Hadoop, Lucene, Kafka,  ActiveMQ, ...

Serveur HTTP

Apache, IIS, Nginx, lighthttpd, GWS, NodeJS, server.py, ...

Protocole HTTP

HyperText Transfert Protocol
Inventé par Tim Berners-Lee, début des années 90
en même temps que le web, HTML, les URLs... 

  • Version actuelle : 1.1 (depuis 1999)
  • Protocole de couche OSI 7
  • Sur TCP
  • Port 80

Version sécurisé sur couche SSL/TLS : HTTPS. Port 443.

GET /index.html HTTP/1.1
Host: www.example.com

Les méthodes

METHOD URL HTTP/1.1
header1:value1
header2:value2 
[...]

(Content)
Une URL = une ressource

  • GET : demander une ressource
  • POST : Envoyer du Content à la ressource (ex: formulaires)

  • HEAD : demander uniquement les headers
  • PUT : ajouter/modifier une ressource
  • DELETE : supprimer une ressource

OPTIONS, CONNECT, TRACE, PATCH

La réponse

HTTP/1.1 StatusCode
header1: value1
header2: value2
[...]

(Content)
Les codes de réponse classiques (liste complète)
  • 200 OK
  • 301 Moved Permanently
  • 302 Found
  • 401 Unauthorized
  • 403 Forbidden
  • 404 Not found
  • 500 Internal Server Error
  • ...
  • 418 I'm a teapot

Les webservices


Sans la contrainte de l'interface HTML, les Webservices peuvent exploiter plus de possibilités de HTTP



Requête
DELETE /g/centrale-patate HTTP/1.1Host: api.my.ecp.fr
Réponse
204 No Content

Les headers

Informations supplémentaires, sous la forme clé-valeur
Présent dans la requête et la réponse

Quelques headers classiques (mais il y en a beaucoup plus !)  
  • Accept, Accept-Encoding, Accept-Language
  • Cache-Control
  • Content-Type
  • Cookie
  • Date
  • Etag
  • Expires
  • Host
  • User-Agent
Inspectez votre navigateur !


Apache : la base

Sous Debian

Installation
aptitude install apache2
aptitude install apache2-mpm-prefork 
aptitude install libapache2-mod-php5
Configuration dans /etc/apache2

  • apache2.conf : Configuration générale. Inclus les fichiers suivants.
  • ports.conf : Configuration des ports.
  • conf.d/ : Configuration additionnelles et tierces.
  • sites-enabled/ : Configuration des sites/VirtualHosts. Lien symboliques depuis sites-available/.
    Bonnes pratiques : Éditer dans sites-available. Faire un fichier par VirtualHost.
  • mods-enabled/  : Configuration des modules Apache. Lien depuis mods-available/


Sous Debian


  • /var/www/ : Racine des sites webs.
  • /var/log/apache2/error.log : Logs d'erreur. Très utile pour chasser les erreurs de configuration Apache !
  • /var/log/apache2/access.log : Logs d'accès aux sites. Utile pour les outils d'analyse du trafic.

Administration de base
/etc/init.d/apache2 info       # Gestion de l'execution du serveur
apachectl status|fullstatus    # État d'execution (des workers) du serveur. mod-status requis.
apachectl configtest           # Vérifie la syntaxe des fichiers de configuration
apachectl -h                   # Et bien plus encore !

a2ensite website               # Activer le site "website" disponible dans sites-available/
a2dissite website              # Le désactiver

a2enmod modulename             # Activer le module "module" disponible dans mods-available/
a2dismod modulename            # Le désactiver

MPM


Multi-Processing Module : Répartition des connections / requêtes sur les ressources machines.

Module central dans la structure d'Apache, un seul à la fois. 

  • MPM Worker : Quelques processus lancent des threads. Une requête par thread. Plus rapide.
  • MPM Prefork : Une requête par processus. Isolation des requêtes, compatible avec bibliothèques non thread-safe.

  • MPM ITKVariante de Prefork permettant l'utilisation de plusieurs utilisateurs UNIX. Rare mais utilisé à VIA.
  • Et bien d'autres ! (ex: MPM Event)

Configuration


Sous la forme attribut – valeur
Sections imbriquées pour spécifier la portée des options
Timeout 10

<IfModule mpm_prefork_module>
    StartServers              20    
    MinSpareServers           50
    MaxSpareServers          100
    ServerLimit             1024
    MaxClients              1024
    MaxRequestsPerChild     5000
</IfModule>

<IfModule mpm_worker_module>
    StartServers          2
    MinSpareThreads      25
    MaxSpareThreads      75
    ThreadLimit          64
    ThreadsPerChild      25
    MaxClients          150
    MaxRequestsPerChild   0
</IfModule>

Configuration


/etc/apache2/apache2.conf est très bien commenté
Et la documentation officielle envoie du pâté

Configuration minimale
Listen 80                                 # port d'écoute
User www-data                             # Utilisateur sous lequel tourne Apache
Group www-data                            # Groupe sous lequel tourne Apache
DocumentRoot /var/www/my-website          # Dossier utilisé comme racine du site web
<Directory /var/www/my-website>           # Restriction de la portée à un dossier
  Options Indexes                         # Active l'option d'affichage de l'index de dossier
  AllowOverride All                       # Autorise les .htaccess à changer la configuration
  Order allow,deny                        # Définit la priorité pour les options Allow/Deny
  Allow from all                          # Autorise le dossier à tous
</Directory>
<Directory />                             # Restriction forte sur le reste des dossiers
    Options FollowSymLinks
    AllowOverride None
    Order deny,allow
    Deny from all
</Directory>

Le multi-domaine


Comment faire quand on a plusieurs sites web ?
On utilise des VirtualHosts

On va déclarer un site web par VirtualHost
Qui correspondra à un fichier dans sites-enabled/

Un VirtualHost donné répondra uniquement à des requêtes avec un header Host spécifique

C'est tellement pratique qu'on va faire un VHost même pour un seul site

VirtualHosts

Listen 80
Listen 443

NameVirtualHost *:80            # On déclare une "interface" qui sera utilisée par des VHosts
NameVirtualHost 127.0.0.1:443   # Peut aussi s'attacher à une IP

<VirtualHost *:80>              # On configure un VHost sur une des interfaces
  ServerName site0.localhost    # Host pour lequel ce VHost va répondre
  DocumentRoot /var/www/site0   # Racine de ce VHost
</VirtualHost>
<VirtualHost *:80>
  ServerName site1.localhost
  DocumentRoot /var/www/site1
</VirtualHost>

<VirtualHost 127.0.0.1:443>
  DocumentRoot /var/www/secure
</VirtualHost>
Quand une requête arrivant sur une interface de VHost ne trouve pas de VHost à ServerName correspondant, c'est le premier déclaré qui l'emporte. (cf. 000-default)

Exemple plus complet


<VirtualHost *:80>
  ServerName my.ecp.fr
  ServerAlias myecp-prod.via.ecp.fr myecp-prod myecp.via.ecp.fr
  DocumentRoot /var/www/myecp
  ServerAdmin support@my.ecp.fr
  
  ErrorLog /var/log/apache2/myecp/error.log
  CustomLog /var/log/apache2/myecp/access.log combined 
  LogLevel info

  <Directory /var/www/myecp/web>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ app.php [QSA,L]

    AllowOverride None
    Options FollowSymLinks
  </Directory>

  Header set X-Custom-Header "Content delivered in %D ms"
  
  AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css  
</Directory>

Common mistakes


  • Toujours lier un VirtualHost à un NameVirtualHost
  • Attention à la portée des configurations
    <VirtualHost *:80>
      DocumentRoot /var/www
      ServerName monsite.com
      <Directory /var/www>
        Options Indexes
      </Directory>
    </VirualHost>
    
    # N'est pas équivalent à 
    <VirtualHost *:80>
      DocumentRoot /var/www
      ServerName monsite.com
    </VirtualHost>
    <Directory /var/www>
      Options Indexes
    </Directory>
  • Ne pas oublier le ServerName
  • Un Listen ou NameVirtualHost en double empêche de démarrer
  • En cas de déplacement, bien mettre à jour VirtualHost et Directory

Modules

Les modules


Il y en a beaucoup beaucoup ! Exemple de ceux à VIA.

mod_autoindexAffiche l'index des dossiers
mod_rewriteRéecriture d'URL
mod_headerModifier les headers
mod_deflateCompression gzip des données
mod_statusPage de status des processus Apache
mod_sslFaire du HTTPS
mod_ldapAuthentification HTTP via LDAP
mod_userdirActive les "people" /~username/
mod_php5Incorpore un interpréteur PHP
mod_cgiInterface CGI
mod_fcgiInterface FastCGI

Contenu dynamique

Contenu dynamique



Idée : utiliser un langage de programmation (PHP, Python, Ruby, Perl...) pour générer du contenu dynamiquement


Deux solutions :
  1. Intégrer un interpréteur directement dans Apache
  2. Faire fonctionner le programme à part, et communiquer avec

Interpréteur intégré


Les processus d'Apache qui répondent aux requêtes intègre un interpréteur directement


En pratique, c'est la méthode classique pour PHP (mod_php)
Mais existe aussi pour d'autres (mod_ruby, mod_python)


Avantages : très simple à mettre en place et gérer

Inconvénients : plus lourd en mémoire, uniquement mpm-prefork

Exécution indépendante


Le serveur HTTP gère et communique avec le programme

  • CGI : Le programme est exécuté pour chaque requête et échange avec le serveur selon CGI. mod_cgi.
  • FCGI : FastCGI. Même principe sauf que le programme tourne en boucle, de manière indépendante. Bien plus rapide. mod_fcgid.

Quelques interfaces spécifiques à un langage (WSGI, Rack...).

Avantages : Plus léger en mémoire, compatibilité MPM, permissions UNIX différentes, autorise des middlewares Inconvénients : Plus complexe à mettre en place, plus lent (PHP)

Setup classique avec Apache2


PHP :
Apache2 + mod_php

Python :
Apache2 + gunicorn ou uwsgi + mod_proxy
Apache2 + mod_wsgi

Ruby :
Apache2 + unicorn + mod_proxy
Apache2 + mod_passenger

Performances

Optimisation Apache


Connexion persistante HTTP : multiple requête sur unique socket TCP
KeepAlive On
MaxKeepAliveRequests 100000
KeepAliveTimeout 4
MPM : à calculer à partir de sa RAM et sa variation de visiteurs.
StartServers             200  # Nombre de processus initiaux
MinSpareServers           50  # Spawn beaucoup de processus d'un coup coûte cher
MaxSpareServers          100  # Le Spare sert de tampon pour éviter ça
ServerLimit             1024  # == MaxClients
MaxClients              1024  # Nombre max de processus
MaxRequestsPerChild     5000  # À garder élevé
Misc.
HostnameLookups     Off     # Pas de résolution DNS pour les logs
AllowOverride       None    # Ne cherche pas de .htaccess 
ServerTokens        Prod    # Réduit la taille du header "Server"
ServerSignature     Off     # Moins d'info dans les pages d'erreur
TraceEnable         Off     # Fonction de test/debug
Option              FollowSymLinks # Ne pas vérifier si un élément est un symlink ou non. À définir au niveau d'un Directoy global.

Performances HTTP


  • Réduire le nombre de requêtes HTTP en réduisant le nombre d'éléments
    • Concaténation CSS/JS : Concaténer tous les fichiers CSS ou JS dans un seul et unique fichier.
    • CSS Sprites : Même idée avec des images. Inclure plusieurs icônes dans une même image mais n'afficher qu'un bout par CSS.
  • CDN : Utiliser des Content Delivery Network (des serveurs rapides spécifiques pour le contenu statique). Exemple : Utiliser jQuery hébergé par Google.
  • DNS : le navigateur ne fait pas plus de 8-10 requêtes simultanées par DNS. Possibilité de distribuer le contenu sur plusieurs DNS (ex: les tuiles des cartes Google Maps).
  • gzip, minified code : réduire la taille des données en utilisant la compression HTTP gzip (mod_deflate) ou en allégeant le code (virer les espaces, ...)

Performances applicatives


  • Un code propre et rapide : Limiter les opérations lentes (BDD, API externes, opérations complexes). Les exécuter en asynchrone au besoin.
  • Un environnement optimal : Dernières versions logicielles. Pour PHP, installer APC.
  • Cache applicatif : Pour les contenus souvent calculer et qui change peu, ne pas hésiter à les mettre en cache dans le code même (exemple : la liste des dernières news. N'expirer le cache qu'à la création d'une nouvelle. Réduit le nombre de requêtes BDD).
  • Rendu : Contenu HTML et Javascript pas trop dégeu ! Quelques guidelines.

Cache HTTP


Super important !

  • Bien comprendre les processus de validation et d'expiration. Très documenté sur la toile.
  • Le configurer proprement sous Apache (mod_headers, mod_expires)
  • Bonus : Utiliser Varnish. Cache intermédiaire entre le client et Apache.

Debug/Administration


Activer mod_status

Aller voir les logs

Utiliser Munin

Ou encore mieux, Datadog <3

THE END

Apache PEW PEW