Pregunta

Tenemos una aplicación de servidor Java que se ejecuta en varias computadoras, todas conectadas a Internet, algunas detrás de firewalls.Necesitamos actualizar de forma remota los archivos JAR y los scripts de inicio desde un sitio central, sin ninguna interrupción notable en la aplicación en sí.

El proceso tiene que ser desatendido e infalible (es decir,no podemos darnos el lujo de estropear la aplicación debido a cortes inoportunos de Internet).

En el pasado hemos usado una variedad de scripts y utilidades externos para manejar tareas similares, pero debido a que tienen sus propias dependencias, el resultado es más difícil de mantener y menos portátil.Antes de hacer algo nuevo, quiero recibir comentarios de la comunidad.

¿Alguien ya ha encontrado una buena solución para esto?¿Tiene alguna idea o sugerencia?

Solo para aclarar:Esta aplicación es un servidor, pero no para aplicaciones web (aquí no hay contenedores de aplicaciones web ni archivos WAR).Es solo un programa Java autónomo.

¿Fue útil?

Solución

No especificaste el tipo de aplicaciones de servidor. Voy a asumir que no estás ejecutando aplicaciones web (ya que implementar un WAR ya hace lo que estás hablando, y muy rara vez necesitas una aplicación web para hacer pull type). actualizaciones.Si está hablando de una aplicación web, la siguiente discusión aún puede aplicarse: simplemente implementará la verificación de actualización y el ping-pong para el archivo WAR en lugar de archivos individuales).

Es posible que desee echar un vistazo a jnlp: WebStart se basa en esto (esta es una tecnología de implementación de aplicaciones cliente), pero estoy bastante seguro de que podría adaptarse para realizar actualizaciones para una aplicación de tipo servidor.De todos modos, jnlp hace un buen trabajo al proporcionar descriptores que pueden usarse para descargar las versiones requeridas de los JAR requeridos...

Algunas ideas generales sobre esto (tenemos varias aplicaciones en el mismo grupo y estamos considerando un mecanismo de actualización automática):

  1. Considere tener un archivo bootstrap.jar que sea capaz de leer un archivo jnlp y descargar los archivos jar necesarios/actualizados antes de iniciar la aplicación.

  2. archivos JAR poder actualizarse incluso mientras se ejecuta una aplicación (al menos en Windows, y ese es el sistema operativo con más probabilidades de bloquear los archivos en ejecución).Puede tener problemas si está utilizando cargadores de clases personalizados, o si tiene un montón de JAR que pueden cargarse o descargarse en cualquier momento, pero si crea mecanismos para evitar esto, entonces debería ser mejor sobrescribir los JAR y luego volver a iniciar la aplicación. suficiente para actualizar.

  3. Aunque es posible sobrescribir archivos JAR, es posible que desee considerar un enfoque de ping-pong para la ruta de su biblioteca (si aún no tiene el iniciador de aplicaciones configurado para leer automáticamente todos los archivos jar en la carpeta lib y agregarlos a la ruta de clase automáticamente, entonces eso es algo que realmente quieres hacer).Así es como funciona el ping-pong:

La aplicación se inicia y analiza lib-ping\version.properties y lib-pong\version.properties y determina cuál es la más nueva.Digamos que lib-ping tiene una versión posterior.El iniciador busca lib-ping*.jar y agrega esos archivos al CP durante el inicio.Cuando realiza una actualización, descarga archivos jar en lib-pong (o copia archivos jar de lib-ping si desea ahorrar ancho de banda y el JAR en realidad no cambió; ¡aunque rara vez vale la pena el esfuerzo!).Una vez que haya copiado todos los JAR en lib-pong, lo último que debe hacer es crear el archivo version.properties (de esa manera se puede detectar y eliminar una actualización interrumpida que resulte en una carpeta lib parcial).Finalmente, reinicia la aplicación y bootstrap detecta que lib-pong es el classpath deseado.

  1. ping-pong como se describe anteriormente permite una reversión.Si lo diseña correctamente, puede tener una parte de su aplicación que pruebe a fondo y luego nunca cambie esa verificación para ver si debería revertir una versión determinada.De esa manera, si cometes un error e implementas algo que daña la aplicación, puedes invalidar la versión.Esta parte de la aplicación sólo tiene que eliminar el archivo version.properties de la carpeta lib-* incorrecta y luego volver a iniciarla.Es importante mantener esta parte simple porque es a prueba de fallas.

  2. Puede tener más de 2 carpetas (en lugar de ping/pong, simplemente tenga lib-yyyymmdd y purgue todas menos las 5 más nuevas, por ejemplo).Esto permite una reversión de JAR más avanzada (¡pero más complicada!).

Otros consejos

Definitivamente deberías echarle un vistazo a OSGi, fue creado solo para estos casos (especialmente para productos integrados) y es utilizado por una gran cantidad de empresas.Puede actualizar los "paquetes" de jar, agregarlos y eliminarlos mientras la aplicación se está ejecutando.Yo no lo he usado, así que no sé acerca de la calidad de los marcos/servidores de código abierto, pero aquí hay un montón de enlaces útiles para comenzar:

http://www.osgi.org/Main/HomePage
http://www.aqute.biz/Code/Bnd
http://blog.springsource.com/2008/02/18/creating-osgi-bundles/
http://blog.springsource.com/
http://www.knopflerfish.org/
http://felix.apache.org/site/index.html

Recomendaría Capistrano para la implementación de múltiples servidores.Si bien está diseñado para implementar aplicaciones Rails, he visto que se usa con éxito para implementar aplicaciones Java.

Enlace:Capistrano 2.0 no sólo para rieles

Los archivos jar no se pueden modificar mientras la JVM se está ejecutando sobre ellos y provocarán errores.Probé tareas similares y lo mejor que se me ocurrió fue hacer una copia del Jar actualizado y realizar la transición del script de inicio para ver ese Jar.Una vez que tenga el Jar actualizado, inícielo y espere a que finalice el Jar antiguo después de darle la señal para que lo haga.Lamentablemente, esto significa una pérdida de GUI, etc.por un segundo, pero serializar la mayoría de las estructuras en Java es fácil y la GUI actual podría transferirse a la aplicación actualizada antes de cerrarse (¡aunque es posible que algunas cosas no sean serializables!).

Es muy difícil hacer que la actualización sea atómica, especialmente si tiene que actualizar la base de datos.

Pero, si no lo hace, lo que puede hacer es primero asegurarse de que su aplicación pueda ejecutarse desde una ruta relativa.Es decir, puede colocar su aplicación en algún directorio y todos los archivos importantes se encuentran en relación con esa ubicación, de modo que su ubicación de instalación real no sea realmente importante.

A continuación, duplique su instalación.Ahora tiene la versión "en ejecución" y tiene la versión "nueva".

Actualice la "nueva" versión utilizando la tecnología que desee (FTP, rsync, cinta de papel, lo que sea que le convenga).

Verifique su instalación (sumas de verificación, pruebas unitarias rápidas, lo que necesite, incluso iníciela en un puerto de prueba si lo desea).

Cuando esté satisfecho con la nueva instalación, elimine la instancia en ejecución original, RENOMBRA el directorio original (aplicación mv aplicación_antigua), cambie el nombre del directorio NUEVO (aplicación mv_nueva aplicación) e inícielo de nuevo.

Su tiempo de inactividad se reduce al tiempo de apagado del servidor y de inicio (ya que el cambio de nombre es "gratuito").

Si por casualidad detectas un error crítico, aún tienes tu versión original ahí.Detenga el nuevo servidor, cámbiele el nombre y reinicie el antiguo.Retroceso muy rápido.

La otra cosa buena es que su infraestructura de servicios es estática (como sus scripts rc, trabajos cron, etc.) ya que apuntan al directorio de "aplicaciones" y no cambia.

También se puede hacer con enlaces suaves en lugar de cambiar el nombre de los directorios.de cualquier manera está bien.

Pero la técnica es simple y casi infalible si su aplicación coopera.

Ahora, si tiene cambios en la base de datos, bueno, ese es un problema desagradable completamente diferente.Idealmente, si puede hacer que los cambios de su base de datos sean "compatibles con versiones anteriores", es de esperar que la versión anterior de la aplicación pueda ejecutarse en el nuevo esquema, pero eso no siempre es posible.

Creo que puedes implementar archivos JAR en caliente si usas un servidor de aplicaciones basado en OSGi como Servidor SpringSource dm.Yo nunca lo he usado, pero conociendo la calidad general del portafolio de Spring, estoy seguro de que vale la pena echarle un vistazo.

Usamos Eclipse, que es el sistema de actualización de OSGi, y nuestra experiencia es muy buena.

¡Recomendado!

La última versión de Java Web Start permite inyectar una aplicación en el caché local sin invocar realmente el programa y se puede marcar como "fuera de línea".Dado que el caché es lo que se utiliza para invocar el programa, se actualizará sólo para la siguiente ejecución.Para que esto funcione, lo más probable es que necesite archivos jar con números de versión en su nombre (p. ej.nuestra-biblioteca-2009-06-01.jar).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top