Actualización de una aplicación web sin tiempo de inactividad

31

Es una aplicación PHP. ¿Cómo puedo minimizar el tiempo de inactividad mientras actualizo toda la base de código?

Simon Hayter
fuente

Respuestas:

44

Lo que generalmente hacemos en el trabajo es:

  • antes de actualizar, la raíz del documento del servidor es:
    • en /www/app-2009-09-01
    • pero se accede a través de un enlace simbólico, llamado /www/application
  • ponemos toda la nueva base de código a /www/app-2009-09-08
  • Una vez que todo el código base está allí:
    • eliminamos el viejo enlace simbólico
    • creamos un nuevo enlace simbólico, todavía llamado /www/application, pero que apunta a las nuevas fuentes:/www/app-2009-09-08
  • Recargamos Apache para forzar la modificación a ser tomada en cuenta.

Todo este proceso se realiza a través de un script automático (lo único que no es automático es que lo iniciemos cuando sea necesario). Esto significa :

  • Todo va rápido (especialmente el cambio de enlace simbólico, que es la parte importante)
  • Sin riesgo de cometer un error: el script ha sido probado y funciona durante meses / años.


Otra ventaja de este procedimiento de enlace simbólico es que es muy fácil "revertir" una actualización si notamos un error catastrófico solo después de poner en producción la nueva versión de las fuentes: solo tenemos que volver a cambiar los enlaces simbólicos.

Por supuesto, esto no le impide probar la nueva versión en su servidor de ensayo antes de ponerla en producción, pero, quién sabe ... A veces, hay un gran error que nadie ha podido ver mientras testing :-(
Por ejemplo, porque no se realizan pruebas de carga de forma regular en la máquina de preparación.
(He visto que la cosa de "retroceso" usaba algo como 4 o 5 veces en 3 años, cada vez, salvó el día y los sitios web ^^)


Aquí hay algún tipo de ejemplo rápido: supongamos que tengo este VirtualHost en mi configuración de 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>

Bastante "estándar" ... Lo único es /www/applicationque no es un directorio real: es solo un enlace simbólico a la versión actual de las fuentes.
Lo que significa que cuando haya puesto las fuentes en el servidor, pero aún no haya cambiado, tendrá algo como esto:

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

Tenga en cuenta que el symlinc apunta a la "versión anterior"

Ahora que la nueva versión se ha subido totalmente al servidor, cambiemos:

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

Y, ahora, los /www/applicationpuntos a la nueva versión de las fuentes:

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

Y solo tenemos que reiniciar Apache:

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

Los tres pasos " eliminar el enlace; crear el nuevo enlace; reiniciar apache " deben realizarse rápidamente; es decir, por un script automatizado, y no por un ser humano.

Usando esta solución:

  • puede tomar todo el tiempo que necesite para cargar la nueva versión de las fuentes: apache no las usará mientras el symlic no haya cambiado
  • cuando todo esté bien, simplemente cambie el enlace simbólico: irá más rápido que cambiar incluso 1 o 2 archivos ... Lo que significa que prácticamente no hay tiempo de inactividad :-)

Y supongo que si usa algún caché de código de operación como APC con la opción estadística en 0, puede significar incluso menos riesgo de tiempo de inactividad.


Por supuesto, esta es la versión "simple": si tiene algunos archivos cargados, por ejemplo, tendrá que usar otro enlace simbólico en algún lugar, u otro VirtualHost o lo que sea ...


Espero que esto sea más claro :-)

Pascal MARTIN
fuente
También es una especie de intercambio de servidores. :-)
Wim ten Brink
mod_rewrite para gestionar enlaces simbólicos?
@gAMBOOKa: no: solo es una cuestión de DocumentRoot de Apache (o VirtualHost DocumentRoot), que es / www / application ;; es decir, el enlace simbólico, sin importar a dónde apunta.
2
Excelente respuesta. Sin embargo, un consejo más: puede hacer que el enlace simbólico ocurra sin desvincularlo. Como se cita: "Los tres pasos ... deben realizarse rápidamente; es decir, mediante un script automatizado y no por un ser humano". El comando mv es una operación atómica, por lo que puede crear un enlace simbólico como 'ln -s / www / app-2011-01-28 / www / application-temp' y luego hacer un 'mv -T / www / application-temp / www / application '.
1
Hay algo que no fue cubierto por el método de enlace simbólico. Tu forma funciona con Apache + mod_php pero podría fallar en lighttpd + fastcgi. En un sitio web de alto tráfico, la solicitud se servirá en el medio del intercambio del enlace que, la dependencia del código php fallará con la versión mixta.
Dennis C
2

¿No puede tomar el código existente y migrar el proyecto a un archivo php de prueba separado, y usarlo mientras realiza sus actualizaciones? Lo que quiero decir es que debe tener un servidor de prueba y un servidor de producción para que cuando tenga que realizar una actualización no incurra en ningún tiempo de inactividad.

Comunidad
fuente
1

Configure un segundo servidor con la base de código actualizada y cámbielos lo más rápido posible. :-)

Si no es posible, asegúrese de que su base de código esté dividida en docenas de partes más pequeñas. Entonces, el tiempo de inactividad se limitaría a solo una subparte uno en ese momento. Los bloques de código más pequeños son más fáciles de reemplazar y la mayoría simplemente continuará ejecutándose sin problemas. Sin embargo, ¡primero intente esto en un entorno de prueba!

Wim ten Brink
fuente
Dado que la aplicación no se ha probado con módulos fragmentados, puede dar lugar a escenarios inesperados.
Lo que significa que esto estaría en su lista de tareas pendientes después de esta actualización. :-) Hazlo más modular y puedes actualizar por módulo.
Wim ten Brink
1
Eso está en la lista de tareas pendientes, pero es un objetivo a largo plazo. Somos una startup joven, por lo que la organización dentro del equipo de desarrollo, naturalmente, llevará un tiempo. = D
1

En primer lugar, a menudo uso y me gusta un método similar a la respuesta de Pascal MARTIN.

Otro método que también me gusta es usar mi SCM para insertar un nuevo código. El proceso exacto depende de su tipo de SCM (git vs svn vs ...). Si está utilizando svn, me gusta crear una rama "en línea" o "producción" que compruebo como la raíz del documento en el servidor. Luego, cada vez que quiero insertar un nuevo código desde otra rama / etiqueta / troncal, simplemente confirmo el nuevo código en la rama "en línea" y ejecuto svn update en la raíz del documento. Esto permite retrocesos muy fáciles, ya que hay un registro de revisión completo de lo que ha subido / bajado al servidor y quién lo hizo y cuándo. También puede ejecutar fácilmente esa rama "en línea" en un cuadro de prueba, lo que le permite examinar la aplicación que está a punto de impulsar.

El proceso es similar para git y otros estilos de SCM, solo modificado para que sea más natural para su estilo de flujo de trabajo.

¿Desea extraer / sondear en lugar de enviar actualizaciones? Solo tenga un trabajo cron u otro mecanismo más inteligente que ejecute automáticamente svn update.

Extra: también puede usar este proceso para hacer una copia de seguridad de los archivos que su aplicación escribió en el disco. Simplemente haga que un trabajo cron o algún otro mecanismo ejecute svn commit. Ahora los archivos que creó su aplicación están respaldados en su SCM, revisión registrada, etc. (por ejemplo, si un usuario actualiza un archivo en el disco, pero quiere que lo revierta, simplemente presione la revisión anterior).


fuente
0

También uso un enfoque similar al de Pascal MARTIN. Pero en lugar de cargar varias versiones de mi aplicación en el servidor de producción, mantengo las "compilaciones" detrás de mi firewall, cada una en un directorio separado con el número de compilación y la fecha. Cuando quiero cargar una nueva versión, uso un script simple que incluye "rsync -avh --delay-updates". El indicador "delay = updates" cargará todo (eso es diferente) a una carpeta temporal hasta que todas las actualizaciones estén allí, y luego moverá todo de una vez al final de la transferencia a sus rutas adecuadas para que la aplicación nunca esté en un estado medio viejo medio nuevo. Tiene el mismo efecto que el método anterior, excepto que solo mantengo una versión de la aplicación en el sitio de producción (lo mejor es tener solo los archivos esenciales desnudos en el servidor de producción, IMO).


fuente