Mettre à jour une application web sans aucun temps d'arrêt

31

C'est une application PHP. Comment puis-je minimiser les temps d'arrêt lors de la mise à jour de la base de code entière?

Simon Hayter
la source

Réponses:

44

Ce que nous faisons généralement, au travail, c'est:

  • avant la mise à jour, la racine du document du serveur est:
    • dans /www/app-2009-09-01
    • mais est accessible via un lien symbolique, appelé /www/application
  • nous avons mis la toute nouvelle base de code /www/app-2009-09-08
  • une fois que toute la base de code est là:
    • on supprime l'ancien lien symbolique
    • nous créons un nouveau lien symbolique, encore appelé /www/application, mais qui pointe vers les nouvelles sources:/www/app-2009-09-08
  • nous rechargeons apache pour forcer la prise en compte de la modification.

Tout ce processus se fait via un script automatique (la seule chose non automatique est que nous le lancions en cas de besoin). Ça signifie :

  • Tout va vite (surtout la commutation de lien symbolique, qui est la partie importante)
  • Aucun risque de faire une erreur: le script a été bien testé et fonctionne depuis des mois / années


Un autre avantage de ce précédent de liens symboliques est qu'il est très facile de "restaurer" une mise à jour si nous remarquons un bug catastrophique seulement après avoir mis la nouvelle version des sources en production: il suffit de basculer les liens symboliques.

Bien sûr, cela ne vous empêche pas de tester la nouvelle version sur votre serveur de transfert avant de la mettre en production - mais, qui sait ... Parfois, il y a un très gros bug que personne n'a pu voir pendant testing :-(
Par exemple, parce qu'il n'y a pas de test de charge effectué régulièrement sur la machine de transfert.
(J'ai vu la chose "rollback" utilisé quelque chose comme 4 ou 5 fois en 3 ans - chaque fois, il sauvé la journée - et les sites Web ^^)


Voici une sorte d'exemple rapide: supposons que j'ai VirtualHost dans ma configuration Apache:

<VirtualHost *>
        ServerName example.com
        DocumentRoot /www/application
        <Directory /www/application>
            # Whatever you might need here (this example is copy-pasted from a test server and test application ^^ )
            Options Indexes FollowSymLinks MultiViews +SymLinksIfOwnerMatch
            AllowOverride All
            php_value   error_reporting 6135
            php_value short_open_tag  on
        </Directory>
</VirtualHost>

Assez "standard" ... La seule chose n'est /www/applicationpas un vrai répertoire: c'est juste un lien symbolique vers la version actuelle des sources.
Ce qui signifie que lorsque vous avez mis les sources sur le serveur, mais pas encore commuté, vous aurez quelque chose comme ceci:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:08 application -> /www/app-2009-09-01

Notez que le symlinc pointe vers "l'ancienne version"

Maintenant que la nouvelle version a été totalement téléchargée sur le serveur, passons:

root@shark:/www
# rm /www/application
root@shark:/www
# ln -s /www/app-2009-09-08 /www/application

Et, maintenant, /www/applicationpointe vers la nouvelle version des sources:

root@shark:/www
# ll
total 8
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-01
drwxr-xr-x 2 root root 4096 2009-09-08 22:07 app-2009-09-08
lrwxrwxrwx 1 root root   19 2009-09-08 22:09 application -> /www/app-2009-09-08

Et il suffit de redémarrer Apache:

root@shark:/www
# /etc/init.d/apache2 restart
 * Restarting web server apache2

Les trois étapes " supprimer le lien; créer le nouveau lien; redémarrer apache " doivent être effectuées rapidement; c'est-à-dire par un script automatisé et non par un être humain.

En utilisant cette solution:

  • vous pouvez prendre autant de temps que nécessaire pour télécharger la nouvelle version des sources: apache ne les utilisera pas tant que le symlic n'a pas été modifié
  • quand tout va bien, il suffit de changer le lien symbolique: cela ira plus vite que de changer même 1 ou 2 fichiers ... Ce qui signifie pratiquement aucun temps d'arrêt :-)

Et si vous utilisez un opcode-cache comme APC avec l'option stat à 0, cela peut signifier encore moins de risques de temps d'arrêt, je suppose.


Bien sûr, c'est la version "simple" - si vous avez des fichiers téléchargés, par exemple, vous devrez utiliser un autre lien symbolique quelque part, ou un autre VirtualHost ou autre ...


J'espère que c'est plus clair :-)

Pascal MARTIN
la source
C'est aussi une sorte d'échange de serveur. :-)
Wim ten Brink
mod_rewrite pour gérer les liens symboliques?
@gAMBOOKa: non: juste une question d'Apache DocumentRoot (ou VirtualHost DocumentRoot), qui est / www / application ;; c'est-à-dire le lien symbolique - peu importe où celui-ci pointe.
2
Super réponse. Une autre astuce, cependant: vous pouvez faire apparaître le lien symbolique sans le dissocier. Comme cité: "Les trois étapes… devraient être faites rapidement, c'est-à-dire par un script automatisé et non par un être humain." La commande mv est une opération atomique, vous pouvez donc créer un lien symbolique comme 'ln -s / www / app-2011-01-28 / www / application-temp' puis faire un 'mv -T / www / application-temp / www / application '.
1
Il y a quelque chose qui n'était pas couvert par la méthode du lien symbolique. Votre chemin fonctionne avec Apache + mod_php mais il pourrait échouer sur lighttpd + fastcgi. Dans un site Web à fort trafic, la demande sera servie au milieu de l'échange du lien, la dépendance au code php échouera avec la version mixte.
Dennis C
2

Vous ne pouvez pas prendre le code existant et migrer le projet dans un fichier php de test séparé, et l'utiliser pendant que vous effectuez vos mises à jour? Ce que je veux dire, c'est que vous devriez avoir un serveur de test et un serveur de production afin que lorsque vous devez effectuer une mise à jour, vous n'encouriez aucun temps d'arrêt.

Communauté
la source
1

Configurez un deuxième serveur avec la base de code mise à jour et changez-les le plus rapidement possible. :-)

Si ce n'est pas possible, assurez-vous que votre base de code est divisée en dizaines de parties plus petites. Le temps d'arrêt serait alors limité à une seule sous-partie à la fois. Les blocs de code plus petits sont plus faciles à remplacer et la plupart continueront de fonctionner sans problème. Essayez d'abord cela dans un environnement de test!

Wim ten Brink
la source
Étant donné que l'application n'a pas été testée avec des modules fragmentés, cela peut entraîner des scénarios inattendus.
Ce qui signifie que ce serait sur votre liste de tâches après cette mise à jour. :-) Rendez-le plus modulaire et vous pouvez mettre à jour par module.
Wim ten Brink le
1
C'est sur la liste des tâches, mais c'est un objectif à long terme. Nous sommes une jeune startup, donc l'organisation au sein de l'équipe de développement prendra naturellement un certain temps. = D
1

Tout d'abord, j'utilise et aime souvent une méthode similaire à la réponse de Pascal MARTIN.

Une autre méthode que j'aime aussi est d'utiliser mon SCM pour pousser un nouveau code. Le processus exact dépend de votre type de SCM (git vs svn vs ...). Si vous utilisez svn, j'aime créer une branche "en ligne" ou "production" que je récupère en tant que racine du document sur le serveur. Ensuite, chaque fois que je veux pousser un nouveau code à partir d'une autre branche / balise / tronc, je valide simplement le nouveau code dans la branche "en ligne" et exécute la mise à jour svn à la racine du document. Cela permet des restaurations très faciles car il existe un journal de révision complet de ce qui est monté / descendu sur le serveur et qui l'a fait et quand. Vous pouvez également exécuter facilement cette branche "en ligne" sur une boîte de test, ce qui vous permet de vérifier l'application que vous êtes sur le point de pousser.

Le processus est similaire pour git et d'autres styles de SCM, juste modifié pour être plus naturel pour leur style de flux de travail.

Vous voulez tirer / interroger au lieu de pousser les mises à jour? Ayez juste un travail cron ou autre, un mécanisme plus intelligent exécute automatiquement la mise à jour svn.

Extra: vous pouvez également utiliser ce processus pour sauvegarder les fichiers que votre application a écrits sur le disque. Ayez juste un travail cron ou un autre mécanisme exécutez svn commit. Maintenant, les fichiers créés par votre application sont sauvegardés dans votre SCM, les révisions enregistrées, etc. (par exemple, si un utilisateur met à jour un fichier sur le disque, mais souhaite que vous le rétablissiez, appuyez simplement sur l'ancienne révision).


la source
0

J'utilise également une approche similaire à celle de Pascal MARTIN. Mais au lieu de télécharger plusieurs versions de mon application sur le serveur de production, je garde les "builds" derrière mon pare-feu, chacune dans un répertoire séparé avec le numéro de build et la date. Lorsque je veux télécharger une nouvelle version, j'utilise un script simple qui inclut "rsync -avh --delay-updates". L'indicateur "delay = updates" téléchargera tout (ce qui est différent) dans un dossier temporaire jusqu'à ce que toutes les mises à jour soient là, puis déplacera tout à la fois à la fin du transfert vers leurs chemins appropriés afin que l'application ne soit jamais dans un état mi-vieux-mi-nouveau. Cela a le même effet que la méthode ci-dessus, sauf que je ne garde qu'une seule version de l'application sur le site de production (il est préférable de n'avoir que les fichiers essentiels nus sur le serveur de production, IMO).


la source