Mostrando entradas con la etiqueta Web Programming. Mostrar todas las entradas
Mostrando entradas con la etiqueta Web Programming. Mostrar todas las entradas

jueves, 6 de marzo de 2014

JMeter: Primeros pasos probando rendimiento de aplicaciones web

Una gran herramienta en la caja de herramientas de todo buen desarrollador de software, es aquella que te permite evaluar el rendimiento de una aplicación. En el caso de aplicaciones web es extremadamente necesario hacer estas pruebas de rendimiento simulando una alta concurrencia de usuarios  debido a la naturaleza concurrente de la web.

Una gran herramienta open source para realizar este tipo de pruebas se llama JMeter de Apache. Con ella puedo crear múltiples solicitudes a una dirección web y medir la respuesta para examinar el compartamiento en términos de rendimiento.


Apache JMeter

Pasos para crear un plan de pruebas sencillo:


  1. Descargar JMeter del sitio web oficial de Apache. En Ubuntu se puede instalar usando el comando: apt-get install jmeter
  2. Agregue un Thread Group al Test Plan: Clic derecho en el test plan ->Add->Threads (Users)->Thread Group
  3. Edite los campos del Thread Group como el número de usuarios y la cantidad de ciclos, entre otros.
  4. Agregamos un HTTP Request: Clic derecho en el Thread Group->Add->Sampler->HTTP Request
  5. Editamos los campos requeridos de acuerdo al tipo de request
  6. Agregamos un listener de acuerdo al tipo de reporte que desemos: Clic derecho en Test Plan->Add->Listener->Graph Results
  7. Damos Start y observamos nuestro gráfico crecer
  8. Interpretamos los resultados y/o ajustamos el plan para obtener la información que requerimos

sábado, 5 de enero de 2013

Aplicaciones Web y Frameworks


La web hoy en día se ha vuelto un ecosistema donde las personas cada vez más se mueven mucho más naturalmente a través de  las diversas interacciones que se dan en este complejo ambiente. Los usuarios finales navegan, suben archivos, hacen consultas, realizan búsquedas, en fin, las interfaces de la web cada vez son más comunes a los ojos de las personas, que esa sensación de tiempos antiguos de que todo lo que tenía que ver con computadoras era super complejo, y solo los "nerds" lo entendían, esta prácticamente en extinción.

Para aquellos que nos ganamos la vida produciendo “1’s y 0’s” para que otros usuarios puedan seguir habitando el mundo de la web, resultamos ser un poco más orgullosos porque podemos “jactarnos” que conocemos algunas capas más abajo del subsuelo de la web. Pero la verdad es que la web es tan compleja que los mismos desarrolladores, debido a las herramientas que nos hemos acostumbrado a usar, somos muchas veces grandes desconocedores de todo lo que sucede más allá de las capas superficiales de la web.

En este post, que es más una traducción libre del capítulo 1 del libro Struts 2 In Action: “Struts 2: the modern web application framework" (Struts 2: el framework de aplicaciones web moderno),  quiero describir algunos puntos básicos que todo ingeniero de la web, particularmente el ingeniero que desarrolla aplicaciones web en la plataforma de Java, debería conocer. Examinaremos la pila tecnológica sobre la cual los frameworks de aplicaciones se montan para poder ocultar y facilitar todas esas funciones, que de lo contrario harían la vida muy difícil a los desarrolladores. 

La pila tecnológica


En una manera muy resumida, según lo muestra la figura, los frameworks de aplicación (de Java) se sitúan sobre dos tecnologías importantes: el protocolo HTTP y la especificación de servlets de java.


La API de Servlet maneja todas las comunicaciones de bajo nivel con la capa HTTP. En tiempos modernos no es considerado una buena práctica programar usando directamente la API, pero conocer lo básico de ella nos ayuda a entender mejor la arquitectura sobre la cual construimos nuestras aplicaciones.

Ya que se menciona el protocolo HTTP, cabe destacar los conceptos básicos que se encierran en este protocolo tan común en nuestra vida diaria. Sin él no podríamos hacer ningún tipo de navegación en Internet. El protocolo HTTP es un protocolo que no guarda estado. Consiste en una serie de mensajes entre un cliente, típicamente un navegador, y un servidor, que puede ser una web o aplicación web, por medio de los cuales se solicitan distintos tipos de datos que al final se despliegan para un usuario. Cabe mencionar que el protocolo HTTP no fue originalmente pensado para considerar la cantidad de información compleja e interacciones de usuarios que ahora se utilizan actualmente en la Internet. Este es un tipo de problema que las aplicaciones web deben solucionar en tiempos modernos.

Debido a la falta de estado entre las peticiones, y al hecho de que todas las peticiones son basadas en texto plano, las aplicaciones web deben ingeniárselas para resolver esa brecha resultante de seguir trabajando sobre un protocolo que fue pensado para servir documentos HTML. Los casos de uso más complicados, como una simple validación de usuario, sería como programar en ensamblador (bueno, tal vez no tanto) si no tuviéramos la ayuda de los frameworks web. Otro detalle quizás desapercibido a la hora de utilizar un framework como Struts es la conversión de datos en la comunicación. Esto se vuelve bastante transparente para la mayoría de los desarrolladores. El protocolo es muy tieso en su comunicación por medio de texto plano, mientras que Java es un lenguaje altamente tipeado. Si tuviéramos que pensar todo el tiempo en nuestras aplicaciones web como convertir texto a entero, por dar un ejemplo, pasaríamos menos tiempo resolviendo los verdaderos casos de uso de la aplicación, y más tiempo haciendo tareas repetitivas y aburridas.

La Java Servlet API


La API de Servlets de Java da un paso más adelante para resolver la gran complejidad de lidiar directamente con el protocolo HTTP. Por medio de la API un programador Java puede interactuar con el protocolo usando una encapsulación en el típico paradigma de programación orientación a objetos. Es por ello que en la API hayamos objetos como el HTTPRequest o el HTTPResponse. En síntesis la API permite recibir requests HTTP, incluyendo los parámetros del query string y datos de formularios, hacer un proceso back-end, y retornar una respuesta al usuario. Todo a traves de código Java.

La unidad básica de empaquetamiento de un servlet se conoce como una aplicación web. Aunque parece una definición simple, esto tiene un sentido en el contexto de servlets. La especificación de servlets define una aplicación web como una colección de servlets, páginas HTML, clases, y otros recursos. Típicamente, una aplicación web requiere de más de un servlet para satisfacer todas las solicitudes de sus clientes. Los servlets y recursos de una aplicación web son empacados en una estructura de directorio estándar  y nombrado con una extensión .war. Un archivo WAR es una versión especializada de un archivo .jar. Significa archivo de aplicación web (Web Application Archive).

Una vez que se tiene este archivo web empaquetado, hay que desplegarlo (deploy) en un contenedor de servlets. El servlet es un tipo especial de aplicación llamado aplicación manejada por ciclo de vida. En este tipo de aplicación uno no ejecuta directamente el servlet sino que el contenedor es el encargado de ejecutar el servlet a través de sus métodos de ciclo de vida, donde el principal es el llamado service(). Cuando una solicitud llega al contenedor, este primero determina cuál servlet es el que tiene que usarse para satisfacerla.

En la siguiente figura se muestra un contenedor con tres aplicaciones web y como a través de una URL se determina cual aplicación y servlet debe satisfacer la solicitud



Otra funcionalidad que agrega la API es la capacidad de manejar sesiones. Como se había mencionado, el protocolo HTTP no tiene estado, lo cual significa que no se puede correlacionar las distintas solicitudes a un servidor con un cliente específico. Sino fuera por la API, habría que ingeniarselas con el uso de galletas y llaves de sesión empotradas en el query string para poder mantener una sesión activa con un usuario específico. Aparte de esta funcionalidad, la API no provee más funciones adicionales, pero es el fundamento a partir del cual se construyen sólidas aplicaciones web, incluyendo los frameworks.

Siguiente nivel


Habiendo entendido, de una manera sintetizada, cuáles son las labores de bajo nivel de la API de servlets, podemos entonces continuar con las tareas que no son tomadas en cuenta por la API, y que por tanto son los frameworks web los que suministran estas capacidades a los desarrolladores.

Ligación (binding) de los parámetros de la solicitud (request) y validación de datos.

Recordamos de nuevo que los parámetros del request viajan en texto plano en el protocolo HTTP, y la API de servlets no provee un proceso automático de conversión a distintos tipos de variables en Java. Puede que esto no sea algo extremadamente complejo de implementar por cuenta de un desarrollador, pero es lo suficientemente repetitivo y monótono como para no dejarlo como una funcionalidad de un framework. La necesidad de la validación de datos es obvio de entender para cualquier desarrollador. El framework lo que permite es definir una manera estructurada y consistente para la validación de formularios.

Llamados a las capas de lógica de negocio y datos

Esta es una de las facultades que no son específicas de una aplicación web. Cualquier aplicación sin importar si es web o de escritorio necesita manejar un tipo de flujo de trabajo donde una solicitud de usuario pasa por las capas de presentación, lógica de negocio y acceso a base de datos, y luego viceversa para enviar la respuesta. Este flujo representa algún tipo de tarea que debe completarse. En algunos frameworks web como Struts, a estas tareas se le conoce como acciones, y el framework es conocido como un framework orientado a acciones.

Renderizacion e internacionalizacion

Lejos estamos de los días aquellos del comienzo de la web donde utilizabamos páginas simples construidas en HTML. Cada vez más los sitios web son mucho más complejos en su interfaz para dar una experiencia mucho más rica al usuario. Tecnologías como Ajax, HTML5 y la creciente penetración de los dispositivos móviles, hacen que sea necesario el soporte de un framework para aliviar la complejidad de la capa de presentación.

Agregado a esto tenemos la necesidad de la internacionalización que es la capacidad de una aplicación de adaptar varios elementos de la misma para acomodarse a una región, país o localidad. Ejemplo simples son el texto desplegado para cambiar a un idioma según el país, el formato de la hora y fecha, la moneda, etc. Ciertamente esto es algo que buscamos que un framework nos lo probea.

¿Qué es un framework?


Un framework es una pieza de software estructural. Se dice que es estructural porque la estructura es quizás la meta principal del framework, más que cualquier otro requerimiento funcional. Un framework trata hacer generalizaciones acerca de las tareas comunes y el flujo de trabajo de un dominio específico. El framework entonces intenta proveer una plataforma sobre la cual las aplicaciones de un dominio pueden ser construidas de manera rapida y eficaz. El framework hace esto de dos maneras principales. Primero, el framework trata de automatizar todas aquellas tareas tediosas del dominio. Segundo, el framework intenta introducir una solución arquitectural elegante al flujo de trabajo común del dominio en cuestión.

En una sola definición podemos decir que un framework es una pieza de software estructural que provee automatización de tareas comunes al dominio, así como una incorporación de una solución arquitectural que puede ser fácilmente extendida por aplicaciones que implementan el framework.

¿Por qué utilizar un framework?


Uno necesariamente no tiene la obligación de utilizar un framework, pero pensar en la alternativas que son omitir el uso de un framework, o crear uno propio, realmente acarrea más desventajas que beneficios.

En el primer caso, al menos que sea una aplicación sea sencilla, el hecho de tener que implementar todas las tareas tediosas y repetitivas del dominio en cuestión, resulta en un código altamente complejo y difícil de mantener, sin mencionar que cansado y agotante. Lo ideal en un proyecto de desarrollo de software es gastar la mayor cantidad de esfuerzo en tareas de alto nivel acorde con el negocio, en lugar de invertirlas en reinventar el agua tibia.

En el segundo caso, son muy limitados los escenarios donde es necesario tener que desarrollar un framework desde cero en lugar de utilizar uno existente, principalmente porque deben darse varias raras condiciones en disponibilidad de recursos: desarrolladores sumamente hábiles, tiempo y dinero, todo esto para gastarlo en un proyecto en primera instancia, sin retorno de inversión a corto o mediano plazo. Y aún si estas condiciones se dan, siguen habiendo desventajas con esta estrategia. Hay que invertir tiempo y dinero en preparar nuevos desarrolladores en una solución local, mientras que si se utiliza un framework popular se pueden contratar desarrolladores ya entrenados. Además los frameworks caseros tienden a erosionarse con el tiempo, mientras que los modernos se mantienen en continua actualización.

Sin duda los frameworks web son casi mandatorios para cualquier proyecto de desarrollo web en la actualidad, sin embargo conocer los pilares de las soluciones web nos ayudan a entender mejor la arquitectura para solucionar los problemas que no son triviales, como rendimiento y escalabilidad.  

martes, 20 de septiembre de 2011

Servlet para descargar archivos

Dejo a disposición como utilizar un servlet para descargar archivos.
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* A simple Servlet to download a file.
* @author gabriel.solano
*
*/
public class DownloadServlet extends HttpServlet{

private static final long serialVersionUID = 4440011247408877539L;

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
downloadFile(resp,
this.getServletContext().getRealPath("/WEB-INF/myFile.pdf"));
}

protected void downloadFile(HttpServletResponse response, String filePath)
throws ServletException, IOException {

File fileToDownload = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(fileToDownload);

ServletOutputStream out = response.getOutputStream();
String mimeType = new MimetypesFileTypeMap().getContentType(filePath);

response.setContentType(mimeType);
response.setContentLength(fileInputStream.available());
response.setHeader( "Content-Disposition", "attachment; filename=\""
+ fileToDownload.getName() + "\"" );

int c;
while((c=fileInputStream.read()) != -1){
out.write(c);
}
out.flush();
out.close();
fileInputStream.close();
}
}

jueves, 25 de agosto de 2011

PHP Cache

Una estrategia de cache es siempre una de las primeras opciones a tomar cuando se requiere mejorar el desempeño de una aplicación. Recientemente tuve que buscar una opción disponible para una aplicación web que estabamos trabajando en PHP, y de las que consulté por Internet, me quedé con la que ofrece este amigo en este artículo.

Esta clase PHPCache utiliza una tabla en base de datos con tres columnas como mecanismo de almacenamiento del cache:
  • PHPCache_key: la llave del objeto a guardar
  • PHPCache_value: el valor a guardar
  • PHPCache_expires: cuando expira el objeto en cache
Nuestro amigo ofrece un código que ejemplifica muy bien el uso de la clase:

require_once 'phpcache.class.php'; // Se incluye la clase de PHPCache.

// Parametros de conexión de la Base de datos.
$database = array(
'type' => 'mysql',
'name' => 'YOUR DATABASE NAME',
'table' => 'PHPCache',
'user' => 'YOUR DATABASE USERNAME',
'pass' => 'YOUR DATABASE USERNAME\'S PASSWORD',
'host' => 'localhost' /* Or maybe IP address of your database server */
);

// Llamado de configuración de la base de datos.
PHPCache::configure($database);
// Se obtiene una única instancia (patrón Singleton).
$cache = PHPCache::instance();

// Se pregunta primero si los resultados ya están en cache.
if( ($results = $cache->get('result_of_some_nasty_code')) !== false ) {
$tpl->assign($results);
/* Or maybe return $results or whatever depending on where you use this */
} else {
// Los datos todavía no estan en cache. Hay que obtenerlos de la manera lenta.
/***********************
* Your slow code here
***********************/
// Inmediatamente se guardan en cache. La siguiente vez no se hará de la forma lenta.
$cache->store('result_of_some_nasty_code', $results_of_your_slow_code, PHPCACHE_1_HOUR * 5); /* Cache for 5 hours */
}

lunes, 11 de abril de 2011

PHP: Configurando bien el path para tus galletas

Recientemente me di cuenta que el parámetro ´path ´ es necesario a la hora de configurar una galleta (cookie en inglés) si se quiere que otra página en un path diferente (no en un subdominio diferente) pueda accesarla. Me tomó rato descubrir esta verdad elemental de las galletas.

Si se desea que cualquier path del mismo subdominio pueda leer la galleta, entonces el path se pone con la típica barra inclinada que representa el directorio raíz.

setcookie("cookieName", "cookieValue", time() * 3600 * 24 * 30 /*30 days*/, "/");

jueves, 3 de diciembre de 2009

Análizando el desempeño de nuestra aplicación web con Eclipse TPTP

Usar una herramienta de profiler (perdón por el anglisismo pero no encuentro una término adecuado en español, se puede decir "perfilador" supongo) es una buena manera de encontrar esos cuellos de botella de nuestra aplicación web.

Hoy quisiera recomendar una herramienta que he utilizado en el pasado. Puede que hayan otras más adecuadas dependiendo del tipo de análisis que se quiera efectuar, pero por ahora describiré rápidamente la que conozco: TPTP (Test and Perfomance Tools Platform) o "Prueba y Plataforma de Herramientas de Desempeño".

En mis propias palabras, un profiler es una herramienta que nos permite tener datos estadísticos para probar aquello que ya sabíamos antes (talvez de manera intituiva) por mucho tiempo, pero necesitabamos alguna herramienta sofisticadilla para culpar el mal desempeño de un código, esperando que no sea el que creamos nosotros :). Poniéndonos serios, el uso de estas herramientas para recopilar datos y resumirlos por nosotros realmente nos quita una carga cuando necesitamos apuntar de manera certera, qué parte de nuestra aplicación está degradando el desempeño.

Primero descargamos e instalamos TPTP en Eclipse. Puede ser descargado en un paquete "todo-en-uno" con la versión Galileo.




Abrimos el proyecto al que deseamos crear el perfil ("profile") y usamos la opción "profile" para comenzar el proyecto:

Clic derecho en el proyecto -> “Profile As“ -> “Profile Configurations...”



Seleccionar la opción de “Tomcat 5.x”:



Seleccionar el tipo de análisis. En este caso estamos seleccionando el Análisis de Tiempo de Ejecución (“Execution Time Analysis”).



Seleccionamos Editar Opciones ("Edit Options") para seleccionar el nivel de detalle del análisis:



Hay algunas otras opciones que pueden ser configuradas pero las dejamos a exploración del lector. Finalmente damos clic on "Profile". Eclipse iniciará el servidor Tomcat y la perspectiva "Profiling and Logging" se abrirá.



Doble clic en "Execution Time Analysis" para abrir la tabla de resumen:



Una vez que el profiler está corriendo, necesitamos navegar localmente en el sitio para que la mayoría, o al menos las partes de interés, de nuestro código sea examinado y así recolectar todos los datos de las diferentes clases de la aplicación.

Este análisis mide la cantidad de tiempo (en segundos) consumido por cada método de cada clase. En la tabla de resumen solamente los 10 primeros paquetes más altos en tiempo base ("base time") son mostrados. No obstante se puede ver el detalle de todos lo paquetes ejecutados si se desea.

Tiempo base (Base Time): La cantidad de tiempo (en segundos) que un método especifico acumuló en todas las llamadas de la apliación. Esto no incluye el tiempo de ejecución de otros métodos anidados (sub llamados a otros métodos).

Tiempo promedio base: (Average base time): Es el tiempo base divido entre el número total de llamados hechos por la aplicación.

Tiempo base acumulado (Cumulative base time): La cantidad de tiempo (en segundos) que al método le toma ejecutarse incluyendo todos los sub llamados hechos por el mismo.
Siempre: Tiempo base acumulado >= Tiempo base (Base Time)

Cabe concluir diciendo que esta operación de recolección de datos por parte del profiler es una operación sumamente pesada que consume muchos recursos del equipo dependiendo de lo complejo de la aplicación web. Es recomendable no hacer otras cosas en el equipo porque sino, por experiencia propia, el Eclipse tiende a congelarse y no responder más.

lunes, 30 de noviembre de 2009

Tu Primer Proyecto Web con Eclipse & Tomcat

Tu primer proyecto web usando Eclipse y Tomcat

Requerimientos:

  1. Instalación de Tomcat (Descarga).
  2. Eclipse IDE. En este post usaré EasyEclipse Expert Java Version: 1.3.1.1 (Descarga).

Siguiendo la línea "Para Newbies", explicaré en cortos pasos una manera rápida de crear tu primer proyecto web con java usando Eclipse como IDE y Tomcat como servidor web. En este caso no se usará un "Super Wizard" para configurar el proyecto sino que se seguiran ciertos pasos manuales para
entender un poco lo que se está haciendo.


1. Primero tenemos que crear nuestro proyecto Java.

File -> New -> Java Project





2. Ahora creamos una clase simple que sera invocada por nuestro código JSP.

Clic derecho en el directorio "src" -> New -> class
Right click on “src” folder ->New ? class

package newbie;  

public class HolaMundo {
public static String getHola() {
return "Hola From Costa Rica, Pura Vida!!!";
}
}


3. Es tiempo de crear la estructura de nuestro directorio "WebContent". Para este simple caso crearemos la siguiente estructura:

HolaMundo
+WebContent
++ pages
++ WEB-INF

4. Dentro del directorio WEB-INF agregaremos un archivo llamado "web.xml". Por el momento vamos a dejarlo simple, pero en el futuro, a medida en que crezca el proyecto, más configuraciones se agregaran a este archivo.

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<!--> More Settings Here <-->

</web-app>


5. Dentro del directorio de "pages" agregaremos un JSP llamado “HolaMundo.jsp”:

<%@ page import="newbie.HolaMundo" %>
<%
String message = HolaMundo.getHola();
%>
<h1><%=message%></h1>

El código de este JSP basicamente incluye nuestra clase Java y despliega el String retornado por el método "getHola()".

6. Antes de configurar nuestro Tomcat necesitamos configurar nuestro "build path". Por defecto Eclipse establece el directorio de salida o "outout folder" (donde los "*.class" para cada uno de los "*.java" se localizan) in "<nombre_proyecto/bin>". Ya que nuestro proyecto es web, necesitamos mover el path a:

“HolaMundo/WebContent/WEB-INF/classes”

Clic derecho en el proyecto ->Build Path-> Configure Build Path... ->Source Tab



7. El último paso es configurar nuestro Tomcat. La manera más fácil es simplemente abrir el archivo "server.xml" localizado en:

<Tomcat Installation>\conf\server.xml

y agregar las siguientes líneas entre las etiquetas “<Host> </Host>”

<Context path="/HolaMundo" reloadable="false" docBase="E:\HolaMundo\WebContent" />

El atributo "path" es un path virtul que apunta a nuestro proyecto indicado por el atributo "docBase".

Si todo fue hecho correctamente lo único que resta es arrancar nuestro Tomcat. Es recomendado instalar un plugin a eclipse, "Tomcat Launcher Plugin", para facilitar las tareas de arrancar y parar el servidor.

Normalmente Tomcat corre en el puerto 8080: