Comunicación entre JVM locales


Mi pregunta: ¿Qué enfoque podría/debería tomar para comunicarse entre dos o más instancias de JVM que se ejecutan localmente?

Una descripción del problema:
Estoy desarrollando un sistema para un proyecto que requiere instancias JVM separadas para aislar ciertas tareas unas de otras por completo.

En su ejecución, la JVM 'padre' creará JVM 'hijo' que esperará ejecutar y luego devolverá los resultados (en el formato de POJO relativamente simple clases, o tal vez datos XML estructurados). Estos resultados no deben ser transferidos usando las pipas SysErr/SysOut/SysIn ya que el hijo puede ya usarlas como parte de su ejecución.

Si una JVM hija no responde con resultados dentro de un cierto tiempo, la JVM padre debería ser capaz de indicar al hijo que deje de procesar, o que mate al proceso hijo. De lo contrario, la JVM secundaria debería salir normalmente al final de completar su tarea.

Investigación hasta ahora:
Soy consciente hay una serie de tecnologías que pueden ser de utilidad por ejemplo,...

  • Usando la biblioteca RMI de Java
  • Usando sockets para transferir objetos
  • Usando bibliotecas de distribución como Cajo, Hessian

...pero estoy interesado en escuchar qué enfoques otros pueden considerar antes de perseguir una de estas opciones, o cualquier otra.

Gracias por cualquier ayuda o consejo sobre esto!

Ediciones:
la Cantidad de datos a transferir- relativamente pequeña, en su mayoría será solo un puñado de POJOs que contienen cadenas que representarán el resultado de la ejecución secundaria. Si cualquier solución sería ineficiente en grandes cantidades de información, es poco probable que sea un problema en mi sistema. La cantidad que se transfiere debe ser bastante estática, por lo que no tiene que ser escalable.

Latencia de la transferencia - no es una preocupación crítica en este caso, aunque si se necesita algún' sondeo ' de resultados, esto debería poder para ser bastante frecuente sin gastos generales significativos, por lo que puedo mantener una interfaz gráfica de usuario sensible en la parte superior de esto en un momento posterior (por ejemplo, barra de progreso)

Author: obfuscation, 2011-02-19

11 answers

Usaría KryoNet con sockets locales, ya que se especializa en gran medida en serialización y es bastante ligero (¡también obtienes Invocación de Método remoto! Lo estoy usando ahora mismo), pero desactive el tiempo de espera de desconexión del socket.

RMI funciona básicamente en el principio de que usted tiene un tipo remoto y que el tipo remoto implementa una interfaz. Esta interfaz es compartida. En su máquina local, vincule la interfaz a través de la biblioteca de RMI al código "inyectado" en memoria desde el RMI biblioteca, el resultado es que tiene algo que satisface la interfaz pero es capaz de comunicarse con el objeto remoto.

 5
Author: Chris Dennett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 18:03:17

No es directamente una respuesta a tu pregunta, sino una sugerencia de una alternativa. ¿Has considerado OSGI ?

Permite ejecutar proyectos java de forma completamente aislada entre sí, dentro de la MISMA jvm. La belleza de esto es que la comunicación entre proyectos es muy fácil con los servicios (ver Especificaciones básicas PDF página 123). De esta manera no hay "serialización" de ningún tipo ya que los datos y las llamadas están todos en la misma jvm.

Además todos sus requisitos de calidad del servicio (tiempo de respuesta, etc...) váyase-solo tiene que preocuparse de si el servicio está ARRIBA o ABAJO en el momento en que desea usarlo. Y para eso tienes una especificación muy agradable que hace eso para usted llamado Servicios Declarativos (Ver Enterprise Spec PDF página 141)

Lo siento por la respuesta fuera de tema, pero pensé que algunas otras personas podrían considerar esto como una alternativa.

Actualización

Para responder a su pregunta sobre seguridad, nunca he considerado tal escenario. No creo que haya una manera de imponer el uso de" memoria " dentro de OSGI.

Sin embargo, hay una forma de comunicarse fuera de JVM entre diferentes tiempos de ejecución de OSGI. Se llama Servicios remotos (ver Enterprise Spec PDF , página 7). También tienen una agradable discusión sobre los factores a tener en cuenta al hacer algo así (ver Falacias 13.1).

La gente de Apache Felix (implementación de OSGI) Creo que tienen implementación de esto con iPOJO, llamado Servicios distribuidos con iPOJO (su envoltura para facilitar el uso de los servicios). Nunca he usado esto, así que ignórame si me equivoco.

 6
Author: drozzy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-20 01:19:30

Akka es otra opción, así como otros frameworks java actor, proporciona comunicación y otras ventajas derivadas del modelo actor.

 5
Author: superfav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 21:12:07

Si no puedes usar stdin/stdout, entonces yo iría con sockets. Necesita algún tipo de capa de serialización en la parte superior de los sockets (como lo haría con stdin/stdout), y RMI es una capa muy fácil de usar y bastante efectiva.

Si usa RMI y encuentra que el rendimiento no es lo suficientemente bueno, cambiaría a un serializador más eficiente: hay muchas opciones.

No me acercaría a los servicios web o XML. Eso parece una completa pérdida de tiempo, probablemente tome más esfuerzo y menos rendimiento que RMI.

 4
Author: Tom Anderson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 17:59:59

Ya no parece que a mucha gente le guste el RMI.

Opciones:

  1. Servicios web. por ejemplo, http://cxf.apache.org
  2. JMX. Ahora, esto es realmente un medio de usar RMI debajo de la mesa, pero funcionaría.
  3. Otros protocolos IPC; usted citó Hessian
  4. Roll-your-own usando sockets, o incluso memoria compartida. (Abra un archivo asignado en el padre, ábralo de nuevo en el hijo. Todavía necesitarías algo para la sincronización.)

Ejemplos de nota son Apache ant (que forkea todo tipo de Jvm para un propósito u otro), Apache maven, y la variante de código abierto del kit de daemonización Tanukisoft.

Personalmente, soy muy fácil con los servicios web, así que ese es el martillo que tiendo a convertir las cosas en clavos. Un servicio típico JAX-WS+JAX-B o JAX-RS+JAX-B es muy poco código con CXF, y gestiona toda la serialización y deserialización de datos para mí.

 3
Author: bmargulies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 20:08:44

Se mencionó anteriormente, pero quería ampliar un poco la sugerencia de JMX. en realidad estamos haciendo más o menos exactamente lo que usted está planeando hacer (de lo que puedo deducir de sus diversos comentarios). aterrizamos en el uso de jmx por una variedad de razones, algunas de las cuales voy a mencionar aquí. por un lado, jmx es todo acerca de la gestión, por lo que en general es un ajuste perfecto para lo que quieres hacer (especialmente si ya planea tener servicios jmx para otras tareas de gestión). cualquier esfuerzo que pongas en las interfaces de jmx hará doble función como api que puede llamar utilizando herramientas de administración de Java como jvisualvm. esto lleva a mi siguiente punto, que es el más relevante para lo que usted quiere. la nueva API Attach en jdk 6 y superior es muy dulce. le permite descubrir y comunicarse dinámicamente con JVM en ejecución. esto permite, por ejemplo, que su proceso "controlador" se bloquee y reinicie y vuelva a encontrar todos los procesos de trabajo existentes. estos son los ingredientes de un sistema muy robusto. fue mencionado anteriormente que jmx básicamente rmi bajo el capó, sin embargo, a diferencia de usar rmi directamente, no necesita administrar todos los detalles de conexión (por ejemplo, tratar con puertos únicos, detectabilidad, etc.). la api attach es un poco una gema oculta en el jdk, ya que no está muy bien documentada. cuando estaba investigando esto inicialmente, no sabía el nombre de la api, así que calcular cómo funcionaba la "magia" en jvisualvm y jconsole fue muy difícil. finalmente, me encontré con un artículo como este uno , que muestra cómo usar la api attach dinámicamente en su propio programa.

 3
Author: jtahlborn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-03 02:14:56

Aunque está diseñado para la comunicación potencialmente remota entre JVM, creo que encontrará que Netty funciona extremadamente bien entre instancias locales de JVM también.

Es probablemente la biblioteca más eficiente / robusta / ampliamente soportada de su tipo para Java.

 2
Author: mikera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 18:12:30

Se ha discutido mucho más arriba. Pero ya sea sockets, rmi, jms, hay un montón de trabajo sucio involucrado. Me gustaría dar consejos akka . Es un modelo basado en actores que se comunican entre sí mediante Mensajes.

La belleza es que los actores pueden estar en la misma JVM u otra (muy poca configuración) y akka se encarga del resto por ti. No he visto una manera más limpia que hacer esto:)

 2
Author: Jatin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-09 09:23:09

Pruebe JGroups si los datos a comunicar no son enormes.

 1
Author: zengr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 18:01:42
 0
Author: Felix Ng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-19 19:40:41

Como mencionaste, obviamente puedes enviar los objetos a través de la red, pero eso es algo costoso sin mencionar el inicio de una JVM separada.

Otro enfoque si solo desea separar sus diferentes mundos dentro de una JVM es cargar las clases con diferentes classloaders. ClassA@CL1!= ClassA@CL2 si son cargados por CL1 y CL2 como cargadores de clase hermanos.

Para habilitar las comunicaciones entre ClassA@CL1 y ClassA@CL2, podría tener tres cargadores de clases.

  • CL1 que carga proceso1
  • CL2 que carga process2 (las mismas clases que en CL1)
  • CL3 que carga clases de comunicación (POJOs y Service).

Ahora deja que CL3 sea el cargador de clases padre de CL1 y CL2.

En las clases cargadas por CL3 puede tener una funcionalidad de envío/recepción de comunicación ligera (send(Pojo)/receive(Pojo)) los POJOs entre clases en CL1 y clases en CL2.

En CL3 se expone un servicio estático que habilita implementaciones desde CL1 y CL2 regístrese para enviar y recibir los POJOs.

 0
Author: Niclas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-04-25 21:55:37