lunes, 24 de junio de 2013

Comunicación entre procesos Java y .Net a través de "named pipes"


Pues bien, el concepto de la comuncación entre procesos (IPC) no es nuevo, y la internet posee mucha información acerca de ese tema. Básicamente el concepto se refiere a cualquier canal de comunicación que pueda existir entre dos procesos que corren simultáneamente en la misma computadora, o entre computadoras diferentes conectadas en una red.

Existen varias técnicas que se han desarrollado para lograr esto, una de ellas es la ya muy conocida comunicación a través de sockets: un proceso que posee una subrutina para escuchar información entrante por un puerto TCP o UDP y otro proceso que le envía información. Este acercamiento funciona muy bien en casi la mayoría de ambientes, sin embargo suelen existir ambientes muy específicos cuando por diversos temas, es necesario buscar otra solución. 

Pensemos un momento en el siguiente escenario: Tengo un proceso que posee una lógica muy especial para una tarea muy específica, y necesito reutilizar su funcionalidad desde una aplicación nueva que correrá en la misma computadora. Necesitamos una comunicación local entre estos procesos y no podemos pensar en soluciones a gran escala como aplicaciones o servicios web, ya que su implementación y la plataforma que necesitan se traduce en demasiado esfuerzo. Hasta este punto puedo pensar en comunicar estas dos aplicaciones por sockets, sin embargo el nivel de seguridad que se necesita no permite abrir puertos en dicho computador. Y para adornar un poco más las cosas, éstas aplicaciones están escritas en lenguajes diferentes. 

Reconozco que el ejemplo expuesto es muy poco trivial, y talvez ya tengan una solución válida y coherente completamente diferente a la que les voy a explicar, sin embargo, procederemos con este supuesto. Luego de ver y entender las principales bondades de utilizar "named pipes" estoy seguro de que ustedes podrán apropiarse de la técnica para situaciones suyas mucho más reales y válidas.

Pues bien, un "named pipe", lo que utilizaremos para comunicar éstas dos aplicaciones, no es otra cosa que un componente que se crea como una tubería entre varios procesos. En Windows, cada una de éstas tuberías tiene un comportamiento parecido al de un socket, y tienen que ser accedidas como si se tratasen de archivos. Así mismo, los named pipes deben ser montados sobre un sistema de archivos diferente a los que los comunes mortales conocen conocidos. Un named pipe en Windows, se monta sobre la unidad especial: "\\.\pipe\".

A continuación muestro un ejemplo de comunicación entre una aplicación escrita en C# (que va a actuar como un servicio oyente de información) y una aplicación escrita en Java (que va a actuar como una aplicación cliente de envío de información) a través de un named pipe con nombre "canal".

Primero veamos la rutina en C# necesaria para escuchar por un dato a través del named pipe:
while (true)
{
 //Crear la instancia del named pipe
 NamedPipeServerStream pipeServer =
 new NamedPipeServerStream("canal", PipeDirection.InOut, 4);
 Console.WriteLine("==> Hilo del Servidor NamedPipe creado.");
 //Esperar por una conexión cliente
 Console.WriteLine("==> Esperando por la conexión de un cliente...");
 pipeServer.WaitForConnection();
 Console.WriteLine("==> Cliente conectado.");
 try
 {
  // Flujo para las solicitudes. 
  StreamReader sr = new StreamReader(pipeServer);
  // Flujo para las respuestas. 
  StreamWriter sw = new StreamWriter(pipeServer);
  sw.AutoFlush = true;
  // Leer la solicitud desde el flujo. 
  string mensaje = sr.ReadLine();
  Console.WriteLine("==> Mensaje del cliente: " + mensaje);
  // Enviar la respuesta por le flujo de salida.
  sw.WriteLine("==>: " + mensaje);
  pipeServer.Disconnect();
 }
 catch (IOException e)
 {
  Console.WriteLine("==>Error: {0}", e.Message);
 }
 pipeServer.Close();
}

Como podemos ver, lo único que hará la aplicación servidor en este ejemplo, será el esperar un mensaje de un cliente, escribirlo en la consola y devolvérselo al cliente como un eco.

Ahora veamos la rutina en Java necesaria para enviar un dato hacia la aplicación servidor (escrita en C#) a través del named pipe:
try {
 // Conectarse al NamedPipe
 RandomAccessFile pipe = new RandomAccessFile("\\\\.\\pipe\\canal","rw");
 String echoText = "Hola mundo de NamedPipes\n";
 // Escribir en el NamedPipe
 pipe.write(echoText.getBytes());
 // Leer respuesta
 String echoResponse = pipe.readLine();
 System.out.println("Response: " + echoResponse);
 pipe.close();
} catch (Exception e) {
 e.printStackTrace();
}

Esta sección de código nos deja ver que para acceder a un NamedPipe desde Java podemos hacer como si se tratase de un archivo de acceso aleatorio, cuya localización está dentro de la unidad especial: "\\.\pipe\".

Al ejecutar el cliente podrán ver que su comportamiento es el esperado, y no hace otra cosa que enviar una cadena de texto y recibir la misma cadena de texto como respuesta.
Funcionalmente este ejemplo no es muy útil, sin embargo es justo lo necesario para que podamos ver y deducir a partir de aquí cómo podremos armar un esquema de comunicación robusto entre dos aplicaciones heterogéneas.

A continuación les dejo los links en donde encontré esta información, con el ejemplo original (que es idéntico al expuesto aquí), y así mismo un link desde donde se podrán descargar los dos proyectos para que los pueda correr y probar. (.Net => Visual Studio 2010, Framework 4.0 y Java => Eclipse Juno, JDK 1.6)

Fuentes:
Rutinas de intercomunicación .Net - Java
Named Pipe en Wikipedia

Archivos:
Proyectos .Net y Java

domingo, 9 de junio de 2013

Pruebas de carga con el incomprendido JMeter - Parte 1.


Bueno, antes de comenzar a leer esto, si son curiosos y si no habían escuchado nunca sobre JMeter, mínimo ya lo han buscado en Google para revisar de qué se trata. De todas maneras lo explicaré desde cero para poder ir entendiendo algunas cosas interesantes que he aprendido acerca de esta herramienta en las últimas semanas.

JMeter es una herramienta OpenSource que permite realizar pruebas de carga sobre nuestras aplicaciones. Las pruebas se pueden realizar sobre casi cualquier elemento de software de nuestra aplicación (una función/procedimiento de base de datos, un método Java, un servicio web, una página web, etc.) y a través de diversos protocolos (TCP/IP, HTTP, JDBC, etc.). Esta herramienta ha sido desarrollada sobre Java y su versatilidad ha sido bien aprovechada pudiendo llegar a tener una herramienta sumamente personalizada para nuestras pruebas de carga.

Una prueba de carga, también conocida como prueba de estrés, o (load test), es una prueba cuya finalidad es medir el rendimiento de nuestra aplicación en escenarios de extrema concurrencia. Cuantos requerimientos simultáneos puede llegar a responder mi servicio web sin que el tiempo de respuesta se vea afectado? Cuantos usuarios simultáneos podrán acceder a mi página web antes de que el servidor web colapse? Las respuestas a este tipo de preguntas que a simple vista son difíciles de conocer, son el objetivo de las pruebas de carga sobre una determinada aplicación.

Bien, lo primero que necesitamos, es tener instalado un JRE (Java Runtime Environment), con la finalidad de poder ejecutar la aplicación que como dijimos anteriormente, está desarrollada en Java. Si tienes alguna duda acerca de lo que es el JRE o cómo instalarlo, puedes revisar esta entrada antes de continuar.
Con un ambiente de ejecución de Java instalado, lo único que necesitamos es el programa. Jmeter puede ser descargado desde su sitio oficial: http://jmeter.apache.org/. Al seguir los vínculos: Download -> Download Releases, encontramos los enlaces a la descarga del programa en dos formatos: tar.gz y zip. En el momento de esta publicación la última versión estable es la 2.9. Así que al descargar el programa (yo prefiero el zip), tendremos un archivo como: apache-jmeter-2.9.zip.

Al descomprimirlo, tendremos el programa listo para ser utilizado. Dentro de la carpeta: "apache-jmeter-2.9\bin" podemos encontrar el archivo "jmeter.bat", que básicamente es el archivo que permitirá ejecutar el programa. (Para poder ejecutarlo sin problemas es necesario tener instalado como mínimo el JRE 1.6. Si no sabes qué es eso, puedes chequear esta entrada para salir de las dudas).

Ahora tenemos a JMeter listo para correr una prueba de carga sobre alguna víctima algún sitio de prueba. Para nuestro primer ejemplo, lo que haremos es "probar" el sitio oficial de JMeter.

Lo único que configuraremos es un escenario que simule 5 peticiones simultáneas al sitio "http://jmeter.apache.org" y ver cómo se comporta cada petición realizada. Para esto seguiremos los siguientes pasos en la aplicación de JMeter:

1. Configurar un Grupo de Hilos
El elemento Grupo de Hilos es el punto de partida de cualquier Plan de Pruebas. Todos los controladores y muestreadores deben estar dentro de un Grupo de Hilos. Como su nombre lo indica, este elemento controla el número de hilos que va a ejecutar nuestra prueba.

Entre las principales propiedades que vamos a editar están:
  • La cantidad de hilos.
  • El tiempo de subida (El tiempo que JMeter tendrá para levantar la cantidad de hilos configurados).
  • La cantidad de veces (iteraciones) que se ejecutará la prueba.
Para configurarlo, seguiremos estos pasos:

Nuevo Plan de Pruebas

Crear nuevo Grupo de Hilos

Configurar el Número de Hilos

2. Configurar una petición HTTP
Este elemento se comporta como un muestreador. Y su función principal es la de realizar una solicitud HTTP hacia un servidor web.

Entre las principales propiedades que vamos a editar están:
  • El nombre del servidor o dirección IP.
  • El método HTTP que se va a usar para realizar la solicitud.
Para configurarlo, seguiremos estos pasos:

Agregar nueva Petición HTTP

Configurar el Servidor web y el Método HTTP

3. Configurar un reporte "Árbol de Resultados"
Este elemento se comporta como un receptor. Y permite visualizar a manera de árbol cada una de las respuestas obtenidas por la ejecución de los muestreadores. Además se puede ver el tiempo que le tomó obtener la respuesta y algunos códigos de respuesta.

Para configurarlo, seguiremos estos pasos:

Agregar nuevo Árbol de Resultados

Luego de esto procederemos a darle click al botón de la flecha verde (Arrancar) para iniciar nuestra prueba. En ese momento, el grupo de hilos lanzará 5 hilos (en nuestro caso) haciendo cinco peticiones HTTP simultáneas al servidor configurado. Los resultados de cada una de esas peticiones podremos verlo en nuestro elemento Árbol de Resultados:

Código de respuesta de cada petición

Datos de respuesta de cada petición

Pues bien, hasta este momento hemos configurado un Plan de Pruebas que lanza 5 peticiones simultáneas a la página inicial de un servidor web. Realmente no estamos probando el servidor web con una carga realmente pesada (Podríamos aumentar la cantidad de hilos o las iteraciones del Grupo de Hilos) y tampoco tenemos resultados descriptivos acerca del comportamiento del servidor frente a cargas pesadas (Podríamos usar un receptor más especializado para esto como el Gráfico de Tiempo de Respuesta), éstos puntos y otros más los cubriremos en la siguiente parte de pseudo-tutorial de JMeter.

Fuente: http://jmeter.apache.org/usermanual

Si les ha parecido interesante la entrada, tienen comentarios, u opiniones acerca de este tema o alguno relacionado, siéntanse en la libertad de comentar. La meta es aprender.