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?
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?
Réponses:
Ce que nous faisons généralement, au travail, c'est:
/www/app-2009-09-01
/www/application
/www/app-2009-09-08
/www/application
, mais qui pointe vers les nouvelles sources:/www/app-2009-09-08
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 :
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/application
pas 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/application
pointe 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:
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 :-)
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.
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!
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).
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).